Primeiro acesso

Olá! Nesse tutorial você irá aprender a replicar tudo que será exibido nessa página!

Para isso, você precisa ter instalado em seu computador 2 programas: o R e o RStudio.
O R é a linguagem de programação e o RStudio a interface gráfica,

Você pode baixar o R e o RStudio através do link https://posit.co/download/rstudio-desktop/

  1. Se é o seu primeiro acesso, clique na caixinha Code no canto superior direito para baixar o código no formato .Rmd, ou seja, RMarkdown.
  2. Abra o RStudio
  3. Clique em File -> Open file -> e selecione esse arquivo .Rmd que você baixou.
  4. Você deve chegar a uma tela semelhante a da figura abaixo

Na primeira vez em que for rodar os códigos aqui no R, será solicitado que instale pacotes. Quando aparecerem caixas de diálogo, clique em Yes.

Pode demorar um pouco esse processo. Para ter uma melhor visualização desse tutorial pressione as teclas Ctrl+Shift+K ou clique no botão Knit acima. Recomendo manter uma aba do navegador com o arquivo tutorial_R.html aberto.

Já podemos rodar o código pela primeira vez!
Para isso, aperte Ctrl+Alt+R ou clique em Run no menu superior e depois em Run All:

Enquanto os pacotes estão sendo instalados, prossiga com a leitura. Deixei alguns conteúdos nas Referências que irão complementar esse documento.

Quando quiser renderizar o código para ter a mesma visualização como a do formato .html use o comando de Knit, o Ctrl+Shift+K, ou caso esteja com um gráfico aberto, clique em Viewer na janela inferior direita.

1 Comandos mais utilizados

Ctrl+Alt+R -> executa TODOS os códigos de uma vez só.

Knit ou Ctrl+Shift+K -> roda TODOS os códigos de uma vez só e renderiza a visualização em formatos .html ou .pdf.

Ctrl+Enter -> executa um “parágrafo” de códigos.

Alt+Enter -> executa o “parágrafo” de códigos mas sem mover o cursor.

Ctrl+Shift+C -> para comentar ou descomentar um intervalo de linhas.

As linhas de código que começam com # são comentários. Elas não impactam o resultado final do código.

Ctrl+Alt+I -> cria um novo code chunk.

Ctrl+I -> Indenta o código (ajusta a tabulação entre as linhas, facilita a leitura do código).

A lista completa de atalhos pode ser conferida no menu superior Tools -> Keyboard Shortcuts Help, ou através do atalho Alt+Shift+K.

2 Passo-a-passo

Importante: Com esse arquivo .Rmd você deve chegar aos mesmos resultados que presentes no arquivo tutorial_R.html.

Vou deixar comentado os pedaços de código que necessitam de alteração obrigatória com a nomenclatura alteracao_ seguido de um número.

Para encontrar facilmente os locais que precisam ser ajustados, basta utilizar o comando Ctrl+F e procurar por alteracao_ e o respectivo número listado abaixo.

  1. Renomear a planilha a ser importada pra facilitar a leitura.
    • nesse caso renomeei a plan gerada pelo RSÁgua de Dados_20221222143305.xls para plan_litoral_medio.xls.
    • você pode usar Ctrl+F e substituir todas as ocorrências de plan_litoral_medio para o nome que você deu à planilha.
  2. Ajustar o caminho do arquivo. (alteracao_1)
    • nesse exemplo estou importando diretamente da pasta de downloads do meu computador: "C:/Users/Léo/Downloads/plan_litoral_medio.xls"
    • Futuramente quero implementar a integração com o Google Sheets.
  3. Verificar o intervalo de dados da planilha. As últimas 10 linhas costumam ser dos sumários, mas o R não entende isso.
    • verificar até qual linha a coluna Índice tem valores registrados, neste caso o Índice vai até 98 (+1 linha de cabeçalho) = linha 99
    • Alterar na parte de importação o intervalo para compreender somente os dados (alteracao_2)
    • Estou tentando descobrir como economizar essa etapa.

3 Pacotes necessários

No code chunk abaixo serão instalados todos os pacotes necessários. Cada pacote contém funções específicas que auxiliam no desenvolvimento da atividade, seja a importação do dado (readr, readxl), na manipulação dos dados (limpeza/tratamento com janitor e lubridate), na visualização (ggplot2, rmarkdown, kableExtra) ou pra praticamente tudo (tidyverse).

pacman::p_load(
  # ETL (extract, transform, load)
  janitor, readr, readxl, lubridate,
  dplyr, 
  tidyverse, 
  glue,
  # Visualização
  ggplot2,
  GGally, 
  rmarkdown, 
  knitr,
  kableExtra,
  ggbeeswarm, 
  ggtext
  # bookdown
)
#googlesheets4

Para acessar a página de ajuda dos pacotes ou das funções, basta usar um ? antes do que se está buscando.

No exemplo abaixo estou verificando os argumentos da função p_load, do pacote pacman. Na sequência abro o menu de ajuda do pacote tidyverse, um dos mais importantes da comunidade R. Outra maneira possível seria utilizando help(package = 'pacman').

?help

4 Importação dos dados

plan_litoral_medio <- read_delim(
  "https://raw.githubusercontent.com/leonardofwink/tutorial_R_fepam/main/planilha_rsagua/plan_litoral_medio%20-%20Dados_Ajustados.tsv", 
  delim = "\t", 
  escape_double = FALSE,
  col_types = cols(
    ÍNDICE = col_number(),
    `CÓD. ESTAÇÃO` = col_character(),
    LATITUDE = col_number(),
    LONGITUDE = col_number(),
    `BACIA HIDROGRÁFICA` = col_character(),
    `RECURSO HÍDRICO` = col_character(),
    REGIÃO = col_character(),
    MUNICÍPIO = col_character(),
    AMBIENTE = col_character(),
    `DATA COLETA` = col_date(format = "%m/%d/%Y"),
    `HORA COLETA` = col_time(format = "%H:%M:%S"),
    `CHUVA 24H` = col_character(),
    ALCALINIDADE = col_number(),
    ALUMÍNIO = col_number(),
    CÁDMIO = col_number(),
    CHUMBO = col_number(),
    CLORETO = col_number(),
    `CLOROFILA A` = col_number(),
    COBRE = col_number(),
    `COLIFORMES TERMOTOLERANTES` = col_number(),
    `COLIFORMES TOTAIS` = col_number(),
    CONDUTIVIDADE = col_number(),
    `CROMO TOTAL` = col_number(),
    `DEMANDA BIOQUÍMICA DE OXIGÊNIO` = col_number(),
    `DEMANDA QUÍMICA DE OXIGÊNIO` = col_number(),
    `ESCHERICHIA COLI` = col_number(),
    FERRO = col_number(),
    `FITOPLANCTON  - CIANOBACTÉRIAS` = col_number(),
    `FOSFATO ORTO` = col_number(),
    `FÓSFORO TOTAL` = col_number(),
    MANGANÊS = col_number(),
    `MERCÚRIO EM MICROGRAMA POR LITRO (UG/L)` = col_number(),
    NÍQUEL = col_number(),
    NITRATO = col_number(),
    `NITROGÊNIO AMONIACAL` = col_number(),
    `NITROGÊNIO ORGÂNICO` = col_number(),
    `NITROGÊNIO TOTAL KJELDAHL` = col_number(),
    `OXIGÊNIO DISSOLVIDO` = col_number(),
    PH = col_number(),
    `PROFUNDIDADE COLETA` = col_number(),
    `PROFUNDIDADE TOTAL` = col_number(),
    SALINIDADE = col_number(),
    `SÓLIDOS DISSOLVIDOS TOTAIS` = col_number(),
    `SÓLIDOS SUSPENSOS TOTAIS` = col_number(),
    `SÓLIDOS TOTAIS` = col_number(),
    `TEMPERATURA DA ÁGUA` = col_number(),
    `TEMPERATURA DO AR` = col_number(),
    `TRANSPARÊNCIA DA ÁGUA` = col_number(),
    TURBIDEZ = col_number(),
    `VAZÃO RECURSO HÍDRICO` = col_number(),
    ZINCO = col_number()
  ),
  locale = locale(
    date_names = "pt", 
    decimal_mark = ",",
    grouping_mark = ""
  ),
  trim_ws = TRUE
) %>%
  janitor::clean_names() %>%
  slice(
    1:(n() - 8) #retirando as ultimas 8 linhas
  ) %>% 
  rename(
    e_coli = escherichia_coli,
    dbo = demanda_bioquimica_de_oxigenio,
    mercurio = mercurio_em_micrograma_por_litro_ug_l
  ) %>%
  mutate(
    municipio = str_to_title(municipio),
    data_coleta = ymd(data_coleta),
    ano_coleta = year(data_coleta),
  ) %>%
  dplyr::select( #reordenando as colunas
    c(1:10),
    ano_coleta,
    everything()
  )
plan_litoral_medio_alterar <- read_excel(
  "C:/Users/Léo/Downloads/plan_litoral_medio.xls", #alteracao_1
  sheet = "Dados_Ajustados", 
  col_types = c(
    "numeric", "text", "numeric", "numeric", "text", 
    "text", "text", "text", "text", "date", 
    "date", "text", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric", "numeric", "numeric", 
    "numeric"),
  range = "A1:AY99", #alteracao_2
  trim_ws = TRUE
) %>% 
  janitor::clean_names() %>% 
  rename(
    e_coli = escherichia_coli,
    dbo = demanda_bioquimica_de_oxigenio,
    mercurio = mercurio_em_micrograma_por_litro_ug_l
  ) %>% 
  mutate(
    municipio = str_to_title(municipio),
    data_coleta = ymd(data_coleta),
    ano_coleta = year(data_coleta),
    # hora_coleta = parse_datetime(hora_coleta),
  ) %>%
  dplyr::select( #reordenando as colunas
    c(1:10),
    ano_coleta,
    everything()
  )

5 Sumários estatísticos

sumario <- plan_litoral_medio %>%
  dplyr::select(cod_estacao, oxigenio_dissolvido, ano_coleta) %>%
  filter(ano_coleta > "2013" &
           ano_coleta <= "2025") %>%
  group_by(cod_estacao) %>%
  summarize(
    min =
      min(oxigenio_dissolvido,
          na.rm = TRUE),
    q1 =
      quantile(oxigenio_dissolvido, 0.25,
               na.rm = TRUE),
    median =
      median(oxigenio_dissolvido,
             na.rm = TRUE),
    mean =
      mean(oxigenio_dissolvido,
           na.rm= TRUE),
    q3 =
      quantile(oxigenio_dissolvido, 0.75,
               na.rm = TRUE),
    max =
      max(oxigenio_dissolvido,
          na.rm = TRUE))

sumario
output
## # A tibble: 6 × 7
##   cod_estacao   min    q1 median  mean    q3   max
##   <chr>       <dbl> <dbl>  <dbl> <dbl> <dbl> <dbl>
## 1 87332500     0     3.5    4.94  4.75  6.57  9.23
## 2 87420130     8.14  8.73   9.06  9.15  9.52 10.6 
## 3 87420150     6.7   8.21   8.41  8.49  8.63  9.83
## 4 87420350     5.93  7.04   8.34  8.07  8.99  9.64
## 5 87420500     4.65  6.87   7.25  7.50  8.61 11.0 
## 6 87510010     2.32  4.23   5.9   5.53  6.71  8.24

5.1 Visualização da estrutura de dados da planilha

Conferir se o tipo dos dados está correto, data em formato de data (date/dttm), código da estação como character (chr), valor medido dos parâmetros como double (dbl).

glimpse(plan_litoral_medio)
output
## Rows: 98
## Columns: 52
## $ indice                      <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,…
## $ cod_estacao                 <chr> "87332500", "87332500", "87332500", "87332…
## $ latitude                    <dbl> -29.91447, -29.91447, -29.91447, -29.91447…
## $ longitude                   <dbl> -50.31819, -50.31819, -50.31819, -50.31819…
## $ bacia_hidrografica          <chr> "Litoral Médio", "Litoral Médio", "Litoral…
## $ recurso_hidrico             <chr> "Lagoa dos Barros", "Lagoa dos Barros", "L…
## $ regiao                      <chr> "Litoral", "Litoral", "Litoral", "Litoral"…
## $ municipio                   <chr> "Osorio", "Osorio", "Osorio", "Osorio", "O…
## $ ambiente                    <chr> "Lêntico", "Lêntico", "Lêntico", "Lêntico"…
## $ data_coleta                 <date> 2016-06-29, 2016-09-26, 2016-12-14, 2017-…
## $ ano_coleta                  <dbl> 2016, 2016, 2016, 2017, 2017, 2017, 2017, …
## $ hora_coleta                 <time> 10:50:00, 11:05:00, 10:21:00, 11:00:00, 1…
## $ chuva_24h                   <chr> "AUSENTE", "AUSENTE", "AUSENTE", "AUSENTE"…
## $ alcalinidade                <dbl> 35.0, 11.0, 7.7, 42.5, 22.1, 14.9, 19.4, 3…
## $ aluminio                    <dbl> NA, NA, NA, NA, NA, NA, NA, 0.0015, 0.0120…
## $ cadmio                      <dbl> NA, NA, NA, NA, 0.003, 0.003, 0.001, 0.001…
## $ chumbo                      <dbl> NA, NA, NA, NA, NA, NA, NA, 0.002, 0.016, …
## $ cloreto                     <dbl> 27.80, 10.10, 9.60, 14.30, 10.10, 8.60, 8.…
## $ clorofila_a                 <dbl> NA, 2.19, 7.64, 40.10, 5.53, 3.56, 2.67, 1…
## $ cobre                       <dbl> NA, NA, NA, NA, 0.0040, 0.0020, 0.0030, 0.…
## $ coliformes_termotolerantes  <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ coliformes_totais           <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ condutividade               <dbl> 123.3, 81.0, 66.6, 139.1, 65.4, 69.0, 75.6…
## $ cromo_total                 <dbl> NA, NA, NA, NA, NA, NA, NA, 0.002, 0.009, …
## $ dbo                         <dbl> 3, 1, 2, 4, 2, 2, 2, 4, 4, 1, 3, 3, 1, 2, …
## $ demanda_quimica_de_oxigenio <dbl> 31, 15, 27, 24, 14, 17, 32, 40, 38, 23, 22…
## $ e_coli                      <dbl> 173.1, 28.8, 122.3, 770.1, 49.6, 34.7, 344…
## $ ferro                       <dbl> NA, NA, NA, NA, 3.120, 3.550, 1.940, 2.960…
## $ fitoplancton_cianobacterias <dbl> 171, 47, 1368, 129, 438, 68, 242, 2901, 18…
## $ fosfato_orto                <dbl> 0.071, 0.101, 0.089, 0.184, 0.109, 0.118, …
## $ fosforo_total               <dbl> 0.105, 0.202, 0.220, 0.233, 0.113, 0.184, …
## $ manganes                    <dbl> NA, NA, NA, NA, 0.051, 0.045, 0.066, 0.112…
## $ mercurio                    <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ niquel                      <dbl> NA, NA, NA, NA, 0.0055, 0.0140, 0.0055, 0.…
## $ nitrato                     <dbl> NA, NA, 0.15, NA, NA, NA, NA, NA, NA, NA, …
## $ nitrogenio_amoniacal        <dbl> 0.032, 0.135, 0.530, 0.603, 0.174, 0.163, …
## $ nitrogenio_organico         <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ nitrogenio_total_kjeldahl   <dbl> NA, 0.910, 1.350, 0.684, 1.120, NA, 1.907,…
## $ oxigenio_dissolvido         <dbl> 5.11, 6.39, 6.77, 3.25, 7.63, 7.50, 3.56, …
## $ ph                          <dbl> 6.48, 7.10, 6.21, 6.67, 6.73, 6.71, 6.27, …
## $ profundidade_coleta         <dbl> 0.88, 0.20, 0.20, 0.20, 0.20, 0.20, 0.20, …
## $ profundidade_total          <dbl> 2.40, 2.75, 2.75, 1.75, 2.15, 2.75, 3.00, …
## $ salinidade                  <dbl> NA, 0.04, NA, 0.07, 0.03, 0.03, 0.03, 0.07…
## $ solidos_dissolvidos_totais  <dbl> 100, 74, 123, 100, 87, 57, 86, 152, 20, 11…
## $ solidos_suspensos_totais    <dbl> 5.0, 15.0, 5.0, 13.0, 5.0, 21.0, 11.0, 15.…
## $ solidos_totais              <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ temperatura_da_agua         <dbl> 14.40, 17.43, 24.89, 23.30, 16.01, 20.36, …
## $ temperatura_do_ar           <dbl> 13.00, 16.00, 19.50, 23.00, 17.16, 21.30, …
## $ transparencia_da_agua       <dbl> 0.4, 0.2, 0.3, 0.3, 0.3, 0.2, 0.3, 0.3, 0.…
## $ turbidez                    <dbl> 23.00, 12.00, 49.10, 23.50, 15.50, 79.60, …
## $ vazao_recurso_hidrico       <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ zinco                       <dbl> NA, NA, NA, NA, 0.0150, 0.0240, 0.0190, 0.…
# str(plan_litoral_medio) #outra maneira de visualizar a eSTRutura 

6 Requisitos pra gerar os gráficos

6.1 Definir o theme

Definindo uma cor de letra e de fundo padrão a ser adotada nos gráficos.

theme_grafs <- function(bg = "white", 
                        coloracao_letra = "black") {
  theme(
    plot.title = 
      element_text(
        hjust = 0.5,
        color = coloracao_letra,
        size = 19),
    
    axis.title.x = 
      # element_text(
      # color = coloracao_letra,
      # size = 15,
      # angle = 0,),
      element_blank(),
    axis.title.y = element_text(
      color = coloracao_letra,
      size = 15,
      angle = 90),
    
    axis.text.x = element_text(
      color = coloracao_letra,
      size = 17),
    axis.text.y = element_text(
      color = coloracao_letra,
      size = 17,
      angle = 0),
    
    strip.background = element_rect(fill = bg,
                                    linetype = 1,
                                    size = 0.5,
                                    color = "black"),
    strip.text = element_text(size = 17),
    panel.background = element_rect(fill = bg),
    plot.background = element_rect(fill = bg),
    plot.margin = margin(l = 5, r = 10,
                         b = 5, t = 5)
  )
}

6.2 Criar função para gerar boxplots com percentis 20 e 80

f <- function(x) {
  r <- quantile(x, probs = c(0.10, 0.20, 0.50, 0.80, 0.90))
  names(r) <- c("ymin", "lower", "middle", "upper", "ymax")
  return(r)
}

7 Gráficos

Atenção: Tomar muito cuidado com a ordem que estão dispostas as estações. Deve-se sempre respeitar o sentido nascente -> foz.

Conferir a ordem das estações através do mapa interativo.

Elas acabam ficando fora de ordem por conta do código de ottobacias Para reordenar as estações, atente-se à função scale_x_discrete descrito no code chunk abaixo:

scale_x_discrete(
  limits = c(
    "87332500",
    "87420130",
    "87420150",
    "87420350",
    "87420500",
    "87510010"
  ),
  labels = c(
    "PM1", "PM2", "PM3", "PM4", "PM5", "PM6"
  )
)+

Obs: Para a Bacia Hidrográfica do Rio Gravataí é necessário

Sempre tomar cuidado com os limites do eixo y. Deixei como padrão o R buscar automaticamente qual o valor mínimo e máximo daquele parâmetro, mas o ideal é que se ajuste caso a caso.

Caso queira alterar o tamanho dos outliers, alterar o size nesse trecho dos códigos:

ggbeeswarm::geom_quasirandom(
     # grouponX = FALSE,
     size = 1.2, 
     alpha = .25,
     width = .07,
   )+

Todos os gráficos foram gerados utilizando como padrão os limites da Resolução nº 357/05 do CONAMA para ambientes lóticos. Caso queira alterar os limites para adequar aos ambientes lênticos, deve-se editar os ymin e ymax de cada retângulo (rect) do referido parâmetro.

Não esquecer que o R entende a casa decimal como ponto, e não como vírgula.

annotate("rect",
         xmin = -Inf, xmax = Inf,
         ymin = 13.3, ymax = Inf,
         alpha = 1,
         fill = "#ac5079")+ #>pior classe
annotate("rect",
         xmin = -Inf, xmax = Inf,
         ymin = 3.7, ymax = 13.3,
         alpha = 1,
         fill = "#fcf7ab")+ #classe 3
annotate("rect",
         xmin = -Inf, xmax = Inf,
         ymin = 0, ymax = 3.7,
         alpha = 1,
         fill = "#8dcdeb")+ #classe 1

7.1 Parâmetros de Qualidade da Água

7.1.1 Oxigênio Dissolvido

(graf_od <- plan_litoral_medio %>%
   ggplot(
     aes(
       x = cod_estacao,
       y = oxigenio_dissolvido,
     )
   )+
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = -Inf, ymax = 2,
            alpha = 1,
            fill = "#ac5079")+ #>pior classe
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 2, ymax = 4,
            alpha = 1,
            fill = "#eb5661")+ #classe 4
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 4, ymax = 5,
            alpha = 1,
            fill = "#fcf7ab")+ #classe 3
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 5, ymax = 6,
            alpha = 1,
            fill = "#70c18c")+ #classe 2
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin= 6, ymax = Inf,
            alpha = 1,
            fill = "#8dcdeb")+ #classe 1
   stat_boxplot(
     fun.data = f,
     geom = 'errorbar',
     width = 0.3,
     position = position_dodge(width = 0.65),
   )+
   stat_boxplot(
     fun.data = f,
     width = 0.7,
     fill = '#F8F8FF',
     color = "black",
     geom = "boxplot",
     outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
   )+
   # facet_wrap(~periodo)+
   labs(
     title = "Oxigênio Dissolvido",
     x= NULL,
     y="mg/L"
   )+
   ggbeeswarm::geom_quasirandom(
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
   scale_y_continuous(
     expand = expansion(mult = c(0,0)),
     n.breaks = 11,
     # limits = c(-0.3,21)
     limits = c(
       min(plan_litoral_medio$oxigenio_dissolvido, na.rm = TRUE),
       max(plan_litoral_medio$oxigenio_dissolvido, na.rm = TRUE)+1)
   )+
   # scale_x_discrete(
   #   limits = c(
   #     "87332500",
   #     "87420130",
   #     "87420150",
   #     "87420350",
   #     "87420500",
   #     "87510010"
   #   ),
   #   labels = c(
   #     "PM1", "PM2", "PM3", "PM4", "PM5", "PM6"
   #   )
   # )+
   geom_smooth(
     method = "lm",
     se = FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
     aes(group = 1),
     alpha = 0.5,
     na.rm = TRUE,
     size = 1
   )+
   theme_grafs()
)

Oxigênio Dissolvido

7.1.2 DBO

(graf_dbo <- ggplot(plan_litoral_medio,
                    aes(x = cod_estacao,
                   y = dbo))+
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 10, ymax = Inf,
            alpha = 1,
            fill = "#ac5079")+ #>pior classe
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 5, ymax = 10,
            alpha = 1,
            fill = "#fcf7ab")+ #classe 3
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 3, ymax = 5,
            alpha = 1,
            fill = "#70c18c")+ #classe 2
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0, ymax = 3,
            alpha = 1,
            fill = "#8dcdeb")+ #classe 1
   stat_boxplot(
      geom = 'errorbar',
      width = 0.3,
      position = position_dodge(width = 0.65),
      fun.data = f,
    )+
    stat_boxplot(
      width = 0.7,
      fill = '#F8F8FF',
      color = "black",
      fun.data = f,
      geom = "boxplot",
      outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
    )+
   # facet_wrap(~periodo)+
   labs(title = "Demanda Bioquímica de Oxigênio",
        x="Estação",
        y="mg/L")+
   ggbeeswarm::geom_quasirandom(
     # grouponX = FALSE,
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
   # scale_x_discrete(limits = c("87398500", 
   #                             "87398980", 
   #                             "87398900", 
   #                             "87398950", 
   #                             "87405500", 
   #                             "87406900", 
   #                             "87409900"),
   #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
   # )+
   scale_y_continuous(expand = expansion(mult = c(0.03,0.03)),
                      n.breaks = 8,
                      limits = c(
                        min(plan_litoral_medio$dbo, na.rm = TRUE),
                        10
                        # max(plan_litoral_medio$dbo, na.rm = TRUE)
                        ),
                      trans = "log10")+
   geom_smooth(method = "lm",
               se=FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
               aes(group=1),
               alpha=.5,
               na.rm = TRUE,
               size = 1)+
   theme_grafs()
)

Demanda Bioquímica de Oxigênio

7.1.3 Escherichia coli

(graf_ecoli <- plan_litoral_medio %>% 
   ggplot(aes(cod_estacao,
              e_coli))+
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 3200, ymax = Inf,
            alpha = 1,
            fill = "#ac5079")+ #>pior classe
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 800, ymax = 3200,
            alpha = 1,
            fill = "#fcf7ab")+ #classe 3
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 160, ymax = 800,
            alpha = 1,
            fill = "#70c18c")+ #classe 2
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0, ymax = 160,
            alpha = 1,
            fill = "#8dcdeb")+ #classe 1
   stat_boxplot(geom = 'errorbar',
                width=0.3,
                position = position_dodge(width = 0.65))+
   geom_boxplot(fill='#F8F8FF',
                color="black",
                outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
                width= 0.7)+
   # facet_wrap(~periodo)+
   labs(title = "*Escherichia coli*",
        x="Estação",
        y="NMP/100mL")+
   scale_y_continuous(expand = expansion(mult = c(0.01, 0.01)),
                      # n.breaks = 9,
                      n.breaks = 6,
                      limits = c(min(plan_litoral_medio$e_coli, na.rm = TRUE),
                                 max(plan_litoral_medio$e_coli, na.rm = TRUE)),
                      trans = "log10",
                      labels = scales::number_format(accuracy = 1,
                                                     decimal.mark = ",",
                                                     big.mark = " "))+
   ggbeeswarm::geom_quasirandom(
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
 # scale_x_discrete(limits = c("87398500",
 #                             "87398980",
 #                             "87398900",
 #                             "87398950",
 #                             "87405500",
 #                             "87406900",
 #                             "87409900"),
 #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
 # )+
 geom_smooth(method = "lm",
 se=FALSE, #stardand error = desvio padrão -> se deixar TRUE gera o intervalo de confiança de 95%
             aes(group=1),
             alpha= 0.5, #transparencia de 50%
             na.rm = TRUE, #remover NAs
             size = 1)+
 theme_grafs()+
   theme(
     axis.text.y = element_text(
       angle = 90,
       # size=15,
       # face=2
     ),
     plot.title = 
       element_markdown(
         hjust = 0.5,
         color = "black",
         size = 19),
   )
)

Escherichia-coli

7.1.4 Fósforo Total

(graf_ptot <- ggplot(plan_litoral_medio,
                     aes(cod_estacao,
                         fosforo_total))+
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0.15, ymax = Inf,
            alpha = 1,
            fill = "#ac5079")+ #>pior classe
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0.1, ymax = 0.15,
            alpha = 1,
            fill = "#fcf7ab")+ #classe 3
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0, ymax = 0.1,
            alpha = 1,
            fill = "#8dcdeb")+ #classe 1
   stat_boxplot(geom = 'errorbar',
                width=0.3,
                position = position_dodge(width = 0.65))+
   geom_boxplot(fill='#F8F8FF',
                color="black",
                outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
                width= 0.7)+
   # facet_wrap(~periodo)+
   labs(title = "Fósforo total",
        x="Estação",
        y="mg/L")+
   scale_y_continuous(expand = expansion(mult = c(0.03,0.03)),
                      n.breaks = 8,
                      limits = c(min(plan_litoral_medio$fosforo_total, na.rm = TRUE),
                                 max(plan_litoral_medio$fosforo_total), na.rm = TRUE),
                      trans = "log10",
                      labels = scales::number_format(accuracy = .001,
                                                     decimal.mark = ",",
                                                     big.mark = " ")
   )+
   ggbeeswarm::geom_quasirandom(
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
   # scale_x_discrete(limits = c("87398500", 
   #                             "87398980", 
   #                             "87398900", 
   #                             "87398950", 
   #                             "87405500", 
   #                             "87406900", 
   #                             "87409900"),
   #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
   # )+
   geom_smooth(method = "lm",
               se=FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
               aes(group=1),
               alpha=.5,
               na.rm = TRUE,
               size = 1)+
   theme_grafs()
)

Fósforo total

7.1.5 Nitrogênio amoniacal

(graf_namon <- ggplot(plan_litoral_medio,
                 aes(cod_estacao,
                     nitrogenio_amoniacal))+
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 13.3, ymax = Inf,
            alpha = 1,
            fill = "#ac5079")+ #>pior classe
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 3.7, ymax = 13.3,
            alpha = 1,
            fill = "#fcf7ab")+ #classe 3
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0, ymax = 3.7,
            alpha = 1,
            fill = "#8dcdeb")+ #classe 1
   stat_boxplot(geom = 'errorbar',
                width=0.3,
                position = position_dodge(width = 0.65))+
   geom_boxplot(fill='#F8F8FF',
                color="black",
                outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
                width= 0.7)+
   # facet_wrap(~periodo)+
   labs(title = "Nitrogênio amoniacal",
        x="Estação",
        y="mg/L")+
   scale_y_continuous(expand = expansion(mult = c(0.01, 0.05)),
                      n.breaks = 9,
                      limits = c(min(plan_litoral_medio$nitrogenio_amoniacal, na.rm = TRUE),
                                 15
                                 # max(plan_litoral_medio$nitrogenio_amoniacal, na.rm = TRUE)
                                 ),
                      trans = "log10",
                      labels = scales::number_format(accuracy = .001,
                                                     decimal.mark = ",",
                                                     big.mark = " "))+
   ggbeeswarm::geom_quasirandom(
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
   # scale_x_discrete(limits = c("87398500", 
   #                             "87398980", 
   #                             "87398900", 
   #                             "87398950", 
   #                             "87405500", 
   #                             "87406900", 
   #                             "87409900"),
   #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
   # )+
   geom_smooth(method = "lm",
               se=FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
               aes(group=1),
               alpha=.5,
               na.rm = TRUE,
               size = 1)+
   theme_grafs()
)

Nitrogênio Amoniacal

7.1.6 Turbidez

(graf_turb <- ggplot(plan_litoral_medio,
                   aes(cod_estacao,
                       turbidez))+
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 100, ymax = Inf,
            alpha = 1,
            fill = "#ac5079")+ #>pior classe
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 40, ymax = 100,
            alpha = 1,
            fill = "#fcf7ab")+ #classe 3
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0, ymax = 40,
            alpha = 1,
            fill = "#8dcdeb")+ #classe 1
   stat_boxplot(geom = 'errorbar',
                width=0.3,
                position = position_dodge(width = 0.65))+
   geom_boxplot(fill='#F8F8FF',
                color="black",
                outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
                width= 0.7)+
   # facet_wrap(~periodo)+
   labs(title = "Turbidez",
        x="Estação",
        y="UNT")+
   scale_y_continuous(expand = expansion(mult = c(0.05, 0.05)),
                      n.breaks = 8,
                      limits = c(
                        # 1,
                        min(plan_litoral_medio$turbidez, na.rm = TRUE),
                        # 500
                        max(plan_litoral_medio$turbidez, na.rm = TRUE)
                      ),
                      trans = "log10",
                      labels = scales::number_format(accuracy = 1,
                                                     decimal.mark = ",",
                                                     big.mark = " "))+
    ggbeeswarm::geom_quasirandom(
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
   # scale_x_discrete(limits = c("87398500", 
   #                             "87398980", 
   #                             "87398900", 
   #                             "87398950", 
   #                             "87405500", 
   #                             "87406900", 
   #                             "87409900"),
   #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
   # )+
   geom_smooth(method = "lm",
               se=FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
               aes(group=1),
               alpha=.5,
               na.rm = TRUE,
               size = 1)+
   theme_grafs()
)

turbidez

7.1.7 pH

(graf_pH <- ggplot(plan_litoral_medio,
                 aes(cod_estacao,
                     ph))+
   annotate("rect",
            xmin=-Inf,
            xmax=Inf,
            ymin=-Inf,
            ymax=6,
            alpha=1,
            fill="#eb5661")+ #classe 4
   annotate("rect",
            xmin=-Inf,
            xmax=Inf,
            ymin=9,
            ymax=Inf,
            alpha=1,
            fill="#eb5661")+ #classe 4
   annotate("rect",
            xmin=-Inf,
            xmax=Inf,
            ymin=6,
            ymax=9,
            alpha=1,
            fill="#8dcdeb")+ #classe 1
   stat_boxplot(geom = 'errorbar',
                width=0.3,
                position = position_dodge(width = 0.65))+
   geom_boxplot(fill='#F8F8FF',
                color="black",
                outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
                width= 0.7)+
   # facet_wrap(~periodo)+
   labs(title = "pH",
        x="Estação",
        y="")+
   scale_y_continuous(expand = expansion(mult = c(0.01, 0.01)),
                      n.breaks = 8,
                      limits = c(4,11),
                      labels = scales::number_format(accuracy = 1,
                                                     decimal.mark = ",",
                                                     big.mark = " ")
                      )+
    ggbeeswarm::geom_quasirandom(
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
   # scale_x_discrete(limits = c("87398500", 
   #                             "87398980", 
   #                             "87398900", 
   #                             "87398950", 
   #                             "87405500", 
   #                             "87406900", 
   #                             "87409900"),
   #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
   # )+
   geom_smooth(method = "lm",
               se=FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
               aes(group=1),
               alpha=.5,
               na.rm = TRUE,
               size = 1)+
   theme_grafs()
)

pH

7.1.8 Sólidos Totais

O parâmetro Sólidos Totais não teve medições no período analisado, então fica armazenado na tabela como valor vazio, ou rNA`.

# (graf_solidos_totais <- ggplot(plan_litoral_medio,
#                                aes(cod_estacao,
#                                    solidos_totais))+
#    annotate("rect",
#             xmin = -Inf, xmax = Inf,
#             ymin = 500, ymax = Inf,
#             alpha = 1,
#             fill="#ac5079")+ #>pior classe
#    annotate("rect",
#             xmin = -Inf, xmax = Inf,
#             ymin = -Inf, ymax = 500,
#             alpha = 1,
#             fill="#8dcdeb")+ #classe 1
#    stat_boxplot(geom = 'errorbar',
#                 width=0.3,
#                 position = position_dodge(width = 0.65))+
#    geom_boxplot(fill='#F8F8FF',
#                 color="black",
#                 outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
#                 width= 0.7)+
#    # facet_wrap(~periodo)+
#    labs(title = "Sólidos totais",
#         x="Estação",
#         y="")+
#    scale_y_continuous(expand = expansion(mult = c(0.01, 0.05)),
#                       n.breaks = 8,
#                       limits = c(0,
#                                  max(plan_litoral_medio$solidos_totais, na.rm = TRUE)
#                                  ),
#                       labels = scales::number_format(accuracy = 1,
#                                                      decimal.mark = ",",
#                                                      big.mark = " "))+
#    ggbeeswarm::geom_quasirandom(
#      size = 1.2,
#      alpha = .25,
#      width = .07,
#    )+
#    # scale_x_discrete(limits = c("87398500", 
#    #                             "87398980", 
#    #                             "87398900", 
#    #                             "87398950", 
#    #                             "87405500", 
#    #                             "87406900", 
#    #                             "87409900"),
#    #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
#    # )+
#    geom_smooth(method = "lm",
#                se=FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
#                aes(group=1),
#                alpha=.5,
#                na.rm = TRUE,
#                size = 1)+
#    theme_grafs()
# )

7.1.9 Condutividade

(graf_cond_elet <- ggplot(plan_litoral_medio,
                          aes(cod_estacao,
                              condutividade))+
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 500, ymax = Inf,
            alpha = 1,
            fill = "#eb5661")+ #classe 4
   annotate("rect",
            xmin = -Inf, xmax = Inf,
            ymin = 0, ymax = 500,
            alpha = 1,
            fill = "#8dcdeb")+ #classe 1
   stat_boxplot(geom = 'errorbar',
                width=0.3,
                position = position_dodge(width = 0.65))+
   geom_boxplot(fill='#F8F8FF',
                color="black",
                outlier.shape = 1, #se deixar NA fica só o jitter, se não, deixa 1
                width= 0.7)+
   # facet_wrap(~periodo)+
   labs(title = "Condutividade elétrica",
        x="Estação",
        y="µmhos/cm")+
   scale_y_continuous(expand = expansion(mult = c(0.05, 0.05)),
                      n.breaks = 8,
                      limits = c(min(plan_litoral_medio$condutividade, na.rm = TRUE),
                                 max(plan_litoral_medio$condutividade, na.rm = TRUE)),
                      trans = "log10",
                      labels = scales::number_format(accuracy = 1,
                                                     decimal.mark = ",",
                                                     big.mark = " "))+
   ggbeeswarm::geom_quasirandom(
     size = 1.2,
     alpha = .25,
     width = .07,
   )+
   # scale_x_discrete(limits = c("87398500", 
   #                             "87398980", 
   #                             "87398900", 
   #                             "87398950", 
   #                             "87405500", 
   #                             "87406900", 
   #                             "87409900"),
   #                  labels = c("PM1", "PM2", "PM3", "PM4", "PM5", "PM6", "PM7")
   # )+
   geom_smooth(method = "lm",
               se=FALSE, #se deixar TRUE gera o intervalo de confiança de 95%
               aes(group=1),
               alpha=.5,
               na.rm = TRUE,
               size = 1)+
   theme_grafs()+
   theme(
     axis.text.y = element_text(
       angle = 90,
       # size=15,
       # face=2
     )
   )
)

condutividade-eletrica

7.2 Análise ao longo do tempo

Para gerar um gráfico ao longo do tempo pra cada uma das estações é necessário alterar o ano_inicial e o ano_final. Também é necessário selecionar qual parâmetro que se quer fazer a visualização.

ano_inicial <- 2015
ano_final <- 2022

(timeline <- plan_litoral_medio %>%
  filter(ano_coleta > ano_inicial &
           ano_coleta <= ano_final) %>%
  dplyr::select(cod_estacao, e_coli, data_coleta) %>%
  group_by(cod_estacao) %>%
  ggplot(
    aes(x = data_coleta,
        y = e_coli,
        color = cod_estacao
    ))+
    geom_line(
      # aes(color = CODIGO),
      na.rm = TRUE)+
    geom_point(
      # aes(color = CODIGO),
      na.rm = TRUE)+
    scale_x_date(
      limits = as.Date(c(
        ymd(glue("{ano_inicial}-01-01")),
        ymd(glue("{ano_final}-01-01"))
        # NA #pode usar NA também
      )),
      expand = c(0.0, 0.0),
      date_breaks = "2 years",
      minor_breaks = "1 years",
      date_labels = "%Y",
    )+
  # geom_smooth(
  #   method = "lm", #regressao linear
  #   se = TRUE, #se deixar TRUE gera o intervalo de confiança de 95%
  #   aes(group = 1),
  #   alpha =.5,
  #   na.rm = TRUE,
  #   size = 0.3,
  #   # fullrange = TRUE,
  #   show.legend = TRUE
  # )+
  stat_smooth(
    geom = "smooth",
    # span = 0.2,
    se = TRUE, #se deixar TRUE gera o intervalo de confiança de 95%
    # aes(group = 1),
    # alpha =.5,
    na.rm = TRUE,
    # size = 0.3,
    fullrange = TRUE,
    show.legend = TRUE
  )+
  facet_wrap(
    ~cod_estacao,
    nrow = 4,
  )+
  theme_bw()
)

7.3 Correlação

parametros_iqa_lit_medio <- plan_litoral_medio %>%
  dplyr::select(cod_estacao,
         ph,
         dbo,
         e_coli,
         nitrogenio_amoniacal,
         # nitro_kjeldahl,
         # nitro_total,
         fosforo_total,
         temperatura_da_agua,
         turbidez,
         solidos_totais,
         oxigenio_dissolvido,
         condutividade,
         ano_coleta
         ) 

parametros_iqa_lit_medio %>% 
  dplyr::select(
    -cod_estacao,
    -ano_coleta,
    -solidos_totais
    ) %>%
  # group_by(cod_estacao) %>%
  rename(
    CE = condutividade,
    OD = oxigenio_dissolvido,
    # ST = solidos_totais,
    Turb = turbidez,
    Temp = temperatura_da_agua,
    Ptot = fosforo_total,
    NAmon = nitrogenio_amoniacal,
    pH = ph,
    DBO = dbo,
    E_coli = e_coli
    # NTK = nitro_kjeldahl
  ) %>% 
  ggcorr(
    method =
    "complete.obs",
    # "pearson",
    # "pairwise",
    name = "Correlação",
    label = TRUE,
    label_alpha = TRUE,
    digits = 3,
    low = "#3B9AB2",
    mid = "#EEEEEE",
    high = "#F21A00",
    # palette = "RdYlBu",
    layout.exp = 0,
    legend.position = "left",
    label_round = 3,
    # legend.size = 18,
    geom = "tile",
    nbreaks = 10,
  )+
  labs(title = "Correlação entre parâmetros físico-químicos na\nBacia Hidrográfica do Litoral Médio")+
  theme_linedraw()+
  theme(
    legend.position = c(0.15, 0.6),
    legend.title = element_text(size = 16),
    legend.text = element_text(size = 14),
    # legend.spacing = unit(element_text(),
                          # units = 5)
    plot.title = element_text(hjust = 0.5,
                              size = 16)
  )

correlação-parametros-qualidade-agua

7.3.1 Correlação entre parâmetros que compõem o IQA com significância estatística

# Gráfico das correlações entre todos os parâmetros com significância
correl_IQA_lit_medio <- parametros_iqa_lit_medio %>%
  dplyr::select(-cod_estacao) %>%
  ggpairs(title = "Correlação entre parâmetros que compõem o IQA",
          axisLabels = "show")
# correl_IQA_lit_medio

7.4 Salvar os gráficos

Replicar esse modelo pros gráficos que deseja salvar.
1. Criar novo code chunk (Ctrl+Alt+I)
2. Copiar a fórmula abaixo
3. Colar nesse novo code chunk
4.

Os gráficos ficarão salvos em uma pasta que irá ser criada a partir do código.

ggsave("graf_od.png",
       plot = graf_od, #alteracao
       path = "./graficos",
       dpi = 300,
       type = "cairo")

8 Mapas

8.1 Pacotes pra geração de mapas

pacman::p_load(raster, leaflet, sf
               # prettymapr, rjson, rosm,
               # ggspatial
               # rgdal, rgeos,
               # gtools, tidyverse, rnaturalearth,
               # rnaturalearthdata, reticulate, maptools,
               # maps, ggplot2, ggspatial, rgeos, ggmap
               )

8.2 Mapa estático

Importando as informações necessárias pra gerar mapas de precipitação.
Fonte: GADM 1, 2

Brasil <- getData(
  'GADM',
  country = 'Brazil',
  level = 3
) %>%
  st_as_sf()
## Warning in getData("GADM", country = "Brazil", level = 3): getData will be removed in a future version of raster
## . Please use the geodata package instead
RS <- subset(Brasil,
             NAME_1 == "Rio Grande do Sul")

lbl <- data.frame(month_abb = month.abb,
                  mes = 1:12)

plan_litoral_medio %>%
  ggplot(
    # aes(x = longtitude,
    #     y = latitude,
    #     map_id = region)
  )+
  geom_sf(
    data = RS
  )+
  theme_bw()
plot

Mapa estático do RS

# Definindo o SRC
RS <- RS %>%
  st_transform (crs = 4674) #4326 = WGS84, 4674 = SIRGAS2000

8.3 Mapa interativo com localização dos pontos de monitoramento

leaflet(RS) %>% 
  addProviderTiles(
    "Esri.WorldImagery" #Imagem de satélite
    # "OpenStreetMap.Mapnik" #OpenStreetMap -> Software livre
  ) %>% 
  addCircleMarkers(
    data = plan_litoral_medio,
    lng = ~longitude,
    lat = ~latitude,
    popup = ~paste(
      "<b>Estação:</b>",{cod_estacao},"<br>",
      "<b>Recurso hídrico:</b>", recurso_hidrico, "<br>",
      "<b>Município:</b>", municipio,
      sep = " "
    )
  ) 

Mapa interativo

8.4 Mapa de precipitação anual

# st_centroid(RS)
# 
# Prec <- getData(
#   "worldclim", 
#   var = "prec", 
#   res = 0.5, 
#   lat = c(-30.033056, -29.68417), #procurar lat long no google e alterar aqui
#   lon = c(-51.230000, -53.80694)
# )
# 
# Prec_RS <- Prec %>% 
#   crop(RS) %>% 
#   mask(RS, na.rm = TRUE)
# 
# plot(Prec_RS)
# 
# PPAnual_RS <- do.call("sum", 
#                        unstack(Prec_RS))
# plot(PPAnual_RS)
# vls <- rasterToPoints(Prec_RS) %>% 
#   as_tibble() %>% 
#   gather(var, value, -x, -y) %>% 
#   mutate(mes = parse_number(var)) %>% 
#   inner_join(., lbl, by = 'mes') %>% 
#   dplyr::select(x, y, month_abb, value) %>% 
#   mutate(month_abb = factor(month_abb, levels = month.abb))
# 
# vls %>% 
#   filter(month_abb == 'Jan')
# 
# summary(vls$value) #descobre o valor mínimo, médio e máximo de precipitação

8.5 Mapa com precipitação mensal

Caso queira gerar um mapa com a precipitação mensal, alternar o include para TRUE. A geração desse mapa demanda bastante processamento, recomendável manter include = FALSE e echo = FALSE.

Ainda precisa ser implementado/ajustado

  • RSÁgua deve buscar dados anteriores a 2015.
  • A Fepam tem os dados de altitude das estações. A partir disso pode ser calculado o % de saturação de Oxigênio Dissolvido, necessário para o cálculo do IQA.
  • Tornar a coluna de chuva_24h como factor.
  • A coluna hora_coleta está com formato incorreto.
  • Gerar um Shiny Web App
  • Tornar a coluna de municipio com apenas a primeira letra maiúscula.
  • Sincronização via GitHub
  • Aprender a gerar o mapa de precipitação mensal pra todo o RS
    • O RS está entre 2 fusos, então acaba “partindo no meio” a figura
  • Futuramente: integração via Google Sheets.

Informações adicionais

E-mail para contato: leonardofwink@gmail.com

GitHub: https://github.com/leonardofwink/

LinkedIn: https://www.linkedin.com/in/leonardofwink/

LS0tDQp0aXRsZTogIlR1dG9yaWFsIC0gY29tbyBnZXJhciBvcyBncsOhZmljb3MgYm94cGxvdCBubyBSIGEgcGFydGlyIGRvIFJTw4FndWEgLSBGZXBhbSINCmF1dGhvcjogIkxlb25hcmRvIEZlcm5hbmRlcyBXaW5rIg0KZW1haWw6ICJsZW9uYXJkb2Z3aW5rQGdtYWlsLmNvbSINCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkLyVtLyVZJylgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGRpc3RpbGw6OmRpc3RpbGxfYXJ0aWNsZToNCiAgICBoaWdobGlnaHQ6IGhhZGRvY2sNCiAgICBrZWVwX21kOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBubw0KICAgICAgc21vb3RoX3Njcm9sbDogbm8NCiAgICB0aGVtZTogZmxhdGx5DQogICAgZmlnX3dpZHRoOiAxMA0KICAgIGZpZ19oZWlnaHQ6IDYuNjYNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICB3b3JkX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIGtlZXBfbWQ6IHllcw0KICBwZGZfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgZ2l0aHViX2RvY3VtZW50Og0KICAgIGh0bWxfcHJldmlldzogdHJ1ZQ0KYWx3YXlzX2FsbG93X2h0bWw6IHllcw0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogY29uc29sZQ0KZmlnLmFsaWduOiBjZW50ZXINCi0tLQ0KDQojIFByaW1laXJvIGFjZXNzbyB7I3NlYy1wcmltZWlyby1hY2Vzc28gLnVubnVtYmVyZWR9DQoNCk9sw6EhIE5lc3NlIHR1dG9yaWFsIHZvY8OqIGlyw6EgYXByZW5kZXIgYSByZXBsaWNhciB0dWRvIHF1ZSBzZXLDoSBleGliaWRvIG5lc3NhIHDDoWdpbmEhXA0KDQpQYXJhIGlzc28sIHZvY8OqIHByZWNpc2EgdGVyIGluc3RhbGFkbyBlbSBzZXUgY29tcHV0YWRvciAyIHByb2dyYW1hczogbyBgUmAgZSBvIGBSU3R1ZGlvYC5cDQpPIFIgw6kgYSBsaW5ndWFnZW0gZGUgcHJvZ3JhbWHDp8OjbyBlIG8gUlN0dWRpbyBhIGludGVyZmFjZSBncsOhZmljYSwNCg0KVm9jw6ogcG9kZSBiYWl4YXIgbyBgUmAgZSBvIGBSU3R1ZGlvYCBhdHJhdsOpcyBkbyBsaW5rIDxodHRwczovL3Bvc2l0LmNvL2Rvd25sb2FkL3JzdHVkaW8tZGVza3RvcC8+XA0KDQoxLiAgU2Ugw6kgbyBzZXUgcHJpbWVpcm8gYWNlc3NvLCBjbGlxdWUgbmEgY2FpeGluaGEgYENvZGVgIG5vIGNhbnRvIHN1cGVyaW9yIGRpcmVpdG8gcGFyYSBiYWl4YXIgbyBjw7NkaWdvIG5vIGZvcm1hdG8gYC5SbWRgLCBvdSBzZWphLCBSTWFya2Rvd24uDQoyLiAgQWJyYSBvIFJTdHVkaW8NCjMuICBDbGlxdWUgZW0gRmlsZSAtXD4gT3BlbiBmaWxlIC1cPiBlIHNlbGVjaW9uZSBlc3NlIGFycXVpdm8gYC5SbWRgIHF1ZSB2b2PDqiBiYWl4b3UuDQo0LiAgVm9jw6ogZGV2ZSBjaGVnYXIgYSB1bWEgdGVsYSBzZW1lbGhhbnRlIGEgZGEgZmlndXJhIGFiYWl4bw0KDQohW10oaW1hZ2VzLzIwMjIxMjI3LTA0MDcyNi0wMDMucG5nKQ0KDQpOYSBwcmltZWlyYSB2ZXogZW0gcXVlIGZvciByb2RhciBvcyBjw7NkaWdvcyBhcXVpIG5vIFIsIHNlcsOhIHNvbGljaXRhZG8gcXVlIGluc3RhbGUgcGFjb3Rlcy4gUXVhbmRvIGFwYXJlY2VyZW0gY2FpeGFzIGRlIGRpw6Fsb2dvLCBjbGlxdWUgZW0gKipgWWVzYCoqLg0KDQpQb2RlIGRlbW9yYXIgdW0gcG91Y28gZXNzZSBwcm9jZXNzby4gUGFyYSB0ZXIgdW1hIG1lbGhvciB2aXN1YWxpemHDp8OjbyBkZXNzZSB0dXRvcmlhbCBwcmVzc2lvbmUgYXMgdGVjbGFzIGBDdHJsK1NoaWZ0K0tgIG91IGNsaXF1ZSBubyBib3TDo28gYEtuaXRgIGFjaW1hLiBSZWNvbWVuZG8gbWFudGVyIHVtYSBhYmEgZG8gbmF2ZWdhZG9yIGNvbSBvIGFycXVpdm8gYHR1dG9yaWFsX1IuaHRtbGAgYWJlcnRvLg0KDQpKw6EgcG9kZW1vcyByb2RhciBvIGPDs2RpZ28gcGVsYSBwcmltZWlyYSB2ZXohXA0KUGFyYSBpc3NvLCBhcGVydGUgYEN0cmwrQWx0K1JgIG91IGNsaXF1ZSBlbSBgUnVuYCBubyBtZW51IHN1cGVyaW9yIGUgZGVwb2lzIGVtIGBSdW4gQWxsYDpcDQohW10oaW1hZ2VzLzIwMjIxMjI3LTAzNTU0My0wMDEucG5nKQ0KDQpFbnF1YW50byBvcyBwYWNvdGVzIGVzdMOjbyBzZW5kbyBpbnN0YWxhZG9zLCBwcm9zc2lnYSBjb20gYSBsZWl0dXJhLiBEZWl4ZWkgYWxndW5zIGNvbnRlw7pkb3MgbmFzIFtSZWZlcsOqbmNpYXNdKCNzZWMtbGlua3Mtw7p0ZWlzKSBxdWUgaXLDo28gY29tcGxlbWVudGFyIGVzc2UgZG9jdW1lbnRvLg0KDQpRdWFuZG8gcXVpc2VyIHJlbmRlcml6YXIgbyBjw7NkaWdvIHBhcmEgdGVyIGEgbWVzbWEgdmlzdWFsaXphw6fDo28gY29tbyBhIGRvIGZvcm1hdG8gYC5odG1sYCB1c2UgbyBjb21hbmRvIGRlIGBLbml0YCwgbyBgQ3RybCtTaGlmdCtLYCwgb3UgY2FzbyBlc3RlamEgY29tIHVtIGdyw6FmaWNvIGFiZXJ0bywgY2xpcXVlIGVtIFZpZXdlciBuYSBqYW5lbGEgaW5mZXJpb3IgZGlyZWl0YS4NCg0KIVtdKGltYWdlcy9wYXN0ZS0xOTdGQ0FGQS5wbmcpDQoNCiMgQ29tYW5kb3MgbWFpcyB1dGlsaXphZG9zIHsjc2VjLWNvbWFuZG9zLW1haXMtdXRpbGl6YWRvc30NCg0KYEN0cmwrQWx0K1JgIC1cPiBleGVjdXRhIFRPRE9TIG9zIGPDs2RpZ29zIGRlIHVtYSB2ZXogc8OzLg0KDQpgS25pdGAgb3UgYEN0cmwrU2hpZnQrS2AgLVw+IHJvZGEgVE9ET1Mgb3MgY8OzZGlnb3MgZGUgdW1hIHZleiBzw7MgZSByZW5kZXJpemEgYSB2aXN1YWxpemHDp8OjbyBlbSBmb3JtYXRvcyBgLmh0bWxgIG91IGAucGRmYC4NCg0KYEN0cmwrRW50ZXJgIC1cPiBleGVjdXRhIHVtICJwYXLDoWdyYWZvIiBkZSBjw7NkaWdvcy4NCg0KYEFsdCtFbnRlcmAgLVw+IGV4ZWN1dGEgbyAicGFyw6FncmFmbyIgZGUgY8OzZGlnb3MgbWFzIHNlbSBtb3ZlciBvIGN1cnNvci4NCg0KYEN0cmwrU2hpZnQrQ2AgLVw+IHBhcmEgY29tZW50YXIgb3UgKmRlc2NvbWVudGFyKiB1bSBpbnRlcnZhbG8gZGUgbGluaGFzLg0KDQo+IEFzIGxpbmhhcyBkZSBjw7NkaWdvIHF1ZSBjb21lw6dhbSBjb20gYCNgIHPDo28gKipjb21lbnTDoXJpb3MqKi4gRWxhcyBuw6NvIGltcGFjdGFtIG8gcmVzdWx0YWRvIGZpbmFsIGRvIGPDs2RpZ28uDQoNCmBDdHJsK0FsdCtJYCAtXD4gY3JpYSB1bSBub3ZvICpjb2RlIGNodW5rKi4NCg0KYEN0cmwrSWAgLVw+IEluZGVudGEgbyBjw7NkaWdvIChhanVzdGEgYSB0YWJ1bGHDp8OjbyBlbnRyZSBhcyBsaW5oYXMsIGZhY2lsaXRhIGEgbGVpdHVyYSBkbyBjw7NkaWdvKS4NCg0KPiBBIGxpc3RhIGNvbXBsZXRhIGRlIGF0YWxob3MgcG9kZSBzZXIgY29uZmVyaWRhIG5vIG1lbnUgc3VwZXJpb3IgVG9vbHMgLVw+IEtleWJvYXJkIFNob3J0Y3V0cyBIZWxwLCBvdSBhdHJhdsOpcyBkbyBhdGFsaG8gYEFsdCtTaGlmdCtLYC4NCg0KIyBQYXNzby1hLXBhc3NvIHsjc2VjLXBhc3NvLWEtcGFzc299DQoNCj4gKipJbXBvcnRhbnRlKio6IENvbSBlc3NlIGFycXVpdm8gYC5SbWRgIHZvY8OqIGRldmUgY2hlZ2FyIGFvcyBtZXNtb3MgcmVzdWx0YWRvcyBxdWUgcHJlc2VudGVzIG5vIGFycXVpdm8gYHR1dG9yaWFsX1IuaHRtbGAuDQo+DQo+IFZvdSBkZWl4YXIgY29tZW50YWRvIG9zIHBlZGHDp29zIGRlIGPDs2RpZ28gcXVlIG5lY2Vzc2l0YW0gZGUgYWx0ZXJhw6fDo28gb2JyaWdhdMOzcmlhIGNvbSBhIG5vbWVuY2xhdHVyYSBgYWx0ZXJhY2FvX2Agc2VndWlkbyBkZSB1bSBuw7ptZXJvLg0KPg0KPiBQYXJhIGVuY29udHJhciBmYWNpbG1lbnRlIG9zIGxvY2FpcyBxdWUgcHJlY2lzYW0gc2VyIGFqdXN0YWRvcywgYmFzdGEgdXRpbGl6YXIgbyBjb21hbmRvIGBDdHJsK0ZgIGUgcHJvY3VyYXIgcG9yIGBhbHRlcmFjYW9fYCBlIG8gcmVzcGVjdGl2byBuw7ptZXJvIGxpc3RhZG8gYWJhaXhvLg0KDQoxLiAgUmVub21lYXIgYSBwbGFuaWxoYSBhIHNlciBpbXBvcnRhZGEgcHJhIGZhY2lsaXRhciBhIGxlaXR1cmEuDQogICAgLSAgIG5lc3NlIGNhc28gcmVub21lZWkgYSBwbGFuIGdlcmFkYSBwZWxvIFJTw4FndWEgZGUgYERhZG9zXzIwMjIxMjIyMTQzMzA1Lnhsc2AgcGFyYSBgcGxhbl9saXRvcmFsX21lZGlvLnhsc2AuDQogICAgLSAgIHZvY8OqIHBvZGUgdXNhciBgQ3RybCtGYCBlIHN1YnN0aXR1aXIgdG9kYXMgYXMgb2NvcnLDqm5jaWFzIGRlIGBwbGFuX2xpdG9yYWxfbWVkaW9gIHBhcmEgbyBub21lIHF1ZSB2b2PDqiBkZXUgw6AgcGxhbmlsaGEuDQoyLiAgQWp1c3RhciBvIGNhbWluaG8gZG8gYXJxdWl2by4gKCoqYWx0ZXJhY2FvXzEqKikNCiAgICAtICAgbmVzc2UgZXhlbXBsbyBlc3RvdSBpbXBvcnRhbmRvIGRpcmV0YW1lbnRlIGRhIHBhc3RhIGRlIGRvd25sb2FkcyBkbyBtZXUgY29tcHV0YWRvcjogYCJDOi9Vc2Vycy9Mw6lvL0Rvd25sb2Fkcy9wbGFuX2xpdG9yYWxfbWVkaW8ueGxzImANCiAgICAtICAgRnV0dXJhbWVudGUgcXVlcm8gaW1wbGVtZW50YXIgYSBpbnRlZ3Jhw6fDo28gY29tIG8gW0dvb2dsZSBTaGVldHNdKCNzZWMtYWluZGEtcHJlY2lzYS1zZXItaW1wbGVtZW50YWRvKS4NCjMuICBWZXJpZmljYXIgbyBpbnRlcnZhbG8gZGUgZGFkb3MgZGEgcGxhbmlsaGEuIEFzIMO6bHRpbWFzIDEwIGxpbmhhcyBjb3N0dW1hbSBzZXIgZG9zIHN1bcOhcmlvcywgbWFzIG8gUiBuw6NvIGVudGVuZGUgaXNzby4NCiAgICAtICAgdmVyaWZpY2FyIGF0w6kgcXVhbCBsaW5oYSBhIGNvbHVuYSBgw41uZGljZWAgdGVtIHZhbG9yZXMgcmVnaXN0cmFkb3MsIG5lc3RlIGNhc28gbyBgw41uZGljZWAgdmFpIGF0w6kgOTggKCsxIGxpbmhhIGRlIGNhYmXDp2FsaG8pID0gbGluaGEgOTkNCiAgICAtICAgQWx0ZXJhciBuYSBwYXJ0ZSBkZSBpbXBvcnRhw6fDo28gbyBpbnRlcnZhbG8gcGFyYSBjb21wcmVlbmRlciBzb21lbnRlIG9zIGRhZG9zICgqKmFsdGVyYWNhb18yKiopDQogICAgLSAgIEVzdG91IHRlbnRhbmRvIGRlc2NvYnJpciBjb21vIGVjb25vbWl6YXIgZXNzYSBldGFwYS4NCg0KIyBQYWNvdGVzIG5lY2Vzc8OhcmlvcyB7I3NlYy1wYWNvdGVzLW5lY2Vzc8OhcmlvcyAucGFjb3Rlc30NCg0KYGBge3IgY29uZmlndXJhbmRvIGV4aWJpci9vY3VsdGFyIGPDs2RpZ28gZSByZXN1bHRhZG9zLCBpbmNsdWRlPUZBTFNFfQ0KaG9va3MgPSBrbml0cjo6a25pdF9ob29rcyRnZXQoKQ0KDQpob29rX2ZvbGRhYmxlID0gZnVuY3Rpb24odHlwZSkgew0KICBmb3JjZSh0eXBlKQ0KICBmdW5jdGlvbih4LCBvcHRpb25zKSB7DQogICAgcmVzID0gaG9va3NbW3R5cGVdXSh4LCBvcHRpb25zKQ0KICAgIA0KICAgIGlmIChpc0ZBTFNFKG9wdGlvbnNbW3Bhc3RlMCgiZm9sZC4iLCB0eXBlKV1dKSkgcmV0dXJuKHJlcykNCiAgICANCiAgICBwYXN0ZTAoDQogICAgICAiPGRldGFpbHM+PHN1bW1hcnk+IiwgdHlwZSwgIjwvc3VtbWFyeT5cblxuIiwNCiAgICAgIHJlcywNCiAgICAgICJcblxuPC9kZXRhaWxzPiINCiAgICApDQogIH0NCn0NCg0Ka25pdHI6OmtuaXRfaG9va3Mkc2V0KA0KICBvdXRwdXQgPSBob29rX2ZvbGRhYmxlKCJvdXRwdXQiKSwNCiAgcGxvdCA9IGhvb2tfZm9sZGFibGUoInBsb3QiKQ0KKQ0KDQojIERpc2FibGUgZm9sZGluZw0KDQojIGBgYHtyLCBmb2xkLm91dHB1dD1GQUxTRSwgZm9sZC5wbG90PUZBTFNFfQ0KIyBybm9ybSgxMCkNCiMgcGxvdChpcmlzKQ0KIyBgYGANCmBgYA0KDQpObyBgY29kZSBjaHVua2AgYWJhaXhvIHNlcsOjbyBpbnN0YWxhZG9zIHRvZG9zIG9zIHBhY290ZXMgbmVjZXNzw6FyaW9zLiBDYWRhIHBhY290ZSBjb250w6ltIGZ1bsOnw7VlcyBlc3BlY8OtZmljYXMgcXVlIGF1eGlsaWFtIG5vIGRlc2Vudm9sdmltZW50byBkYSBhdGl2aWRhZGUsIHNlamEgYSBpbXBvcnRhw6fDo28gZG8gZGFkbyAoYHJlYWRyYCwgYHJlYWR4bGApLCBuYSBtYW5pcHVsYcOnw6NvIGRvcyBkYWRvcyAobGltcGV6YS90cmF0YW1lbnRvIGNvbSBgamFuaXRvcmAgZSBgbHVicmlkYXRlYCksIG5hIHZpc3VhbGl6YcOnw6NvIChgZ2dwbG90MmAsIGBybWFya2Rvd25gLCBga2FibGVFeHRyYWApIG91IHByYSBwcmF0aWNhbWVudGUgdHVkbyAoYHRpZHl2ZXJzZWApLg0KDQpgYGB7ciBQYWNvdGVzIG5lY2Vzc8OhcmlvcywgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gVFJVRX0NCnBhY21hbjo6cF9sb2FkKA0KICAjIEVUTCAoZXh0cmFjdCwgdHJhbnNmb3JtLCBsb2FkKQ0KICBqYW5pdG9yLCByZWFkciwgcmVhZHhsLCBsdWJyaWRhdGUsDQogIGRwbHlyLCANCiAgdGlkeXZlcnNlLCANCiAgZ2x1ZSwNCiAgIyBWaXN1YWxpemHDp8Ojbw0KICBnZ3Bsb3QyLA0KICBHR2FsbHksIA0KICBybWFya2Rvd24sIA0KICBrbml0ciwNCiAga2FibGVFeHRyYSwNCiAgZ2diZWVzd2FybSwgDQogIGdndGV4dA0KICAjIGJvb2tkb3duDQopDQojZ29vZ2xlc2hlZXRzNA0KYGBgDQoNClBhcmEgYWNlc3NhciBhIHDDoWdpbmEgZGUgYWp1ZGEgZG9zIHBhY290ZXMgb3UgZGFzIGZ1bsOnw7VlcywgYmFzdGEgdXNhciB1bSBgP2AgYW50ZXMgZG8gcXVlIHNlIGVzdMOhIGJ1c2NhbmRvLiAgDQoNCk5vIGV4ZW1wbG8gYWJhaXhvIGVzdG91IHZlcmlmaWNhbmRvIG9zIGFyZ3VtZW50b3MgZGEgZnVuw6fDo28gYHBfbG9hZGAsIGRvIHBhY290ZSBgcGFjbWFuYC4gTmEgc2VxdcOqbmNpYSBhYnJvIG8gbWVudSBkZSBhanVkYSBkbyBwYWNvdGUgYHRpZHl2ZXJzZWAsIHVtIGRvcyBtYWlzIGltcG9ydGFudGVzIGRhIGNvbXVuaWRhZGUgUi4gT3V0cmEgbWFuZWlyYSBwb3Nzw612ZWwgc2VyaWEgdXRpbGl6YW5kbyBgaGVscChwYWNrYWdlID0gJ3BhY21hbicpYC4NCg0KIVs/aGVscF0oaW1hZ2VzLzIwMjIxMjI3LTE2MjMzNS0wMDIucG5nKQ0KDQojIEltcG9ydGHDp8OjbyBkb3MgZGFkb3MgeyNzZWMtaW1wb3J0YcOnw6NvLWRvcy1kYWRvc30NCg0KYGBge3IgcmVwbGljYW5kbyBpbXBvcnRhw6fDo28gZG9zIGRhZG9zLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KcGxhbl9saXRvcmFsX21lZGlvIDwtIHJlYWRfZGVsaW0oDQogICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vbGVvbmFyZG9md2luay90dXRvcmlhbF9SX2ZlcGFtL21haW4vcGxhbmlsaGFfcnNhZ3VhL3BsYW5fbGl0b3JhbF9tZWRpbyUyMC0lMjBEYWRvc19BanVzdGFkb3MudHN2IiwgDQogIGRlbGltID0gIlx0IiwgDQogIGVzY2FwZV9kb3VibGUgPSBGQUxTRSwNCiAgY29sX3R5cGVzID0gY29scygNCiAgICDDjU5ESUNFID0gY29sX251bWJlcigpLA0KICAgIGBDw5NELiBFU1RBw4fDg09gID0gY29sX2NoYXJhY3RlcigpLA0KICAgIExBVElUVURFID0gY29sX251bWJlcigpLA0KICAgIExPTkdJVFVERSA9IGNvbF9udW1iZXIoKSwNCiAgICBgQkFDSUEgSElEUk9HUsOBRklDQWAgPSBjb2xfY2hhcmFjdGVyKCksDQogICAgYFJFQ1VSU08gSMONRFJJQ09gID0gY29sX2NoYXJhY3RlcigpLA0KICAgIFJFR0nDg08gPSBjb2xfY2hhcmFjdGVyKCksDQogICAgTVVOSUPDjVBJTyA9IGNvbF9jaGFyYWN0ZXIoKSwNCiAgICBBTUJJRU5URSA9IGNvbF9jaGFyYWN0ZXIoKSwNCiAgICBgREFUQSBDT0xFVEFgID0gY29sX2RhdGUoZm9ybWF0ID0gIiVtLyVkLyVZIiksDQogICAgYEhPUkEgQ09MRVRBYCA9IGNvbF90aW1lKGZvcm1hdCA9ICIlSDolTTolUyIpLA0KICAgIGBDSFVWQSAyNEhgID0gY29sX2NoYXJhY3RlcigpLA0KICAgIEFMQ0FMSU5JREFERSA9IGNvbF9udW1iZXIoKSwNCiAgICBBTFVNw41OSU8gPSBjb2xfbnVtYmVyKCksDQogICAgQ8OBRE1JTyA9IGNvbF9udW1iZXIoKSwNCiAgICBDSFVNQk8gPSBjb2xfbnVtYmVyKCksDQogICAgQ0xPUkVUTyA9IGNvbF9udW1iZXIoKSwNCiAgICBgQ0xPUk9GSUxBIEFgID0gY29sX251bWJlcigpLA0KICAgIENPQlJFID0gY29sX251bWJlcigpLA0KICAgIGBDT0xJRk9STUVTIFRFUk1PVE9MRVJBTlRFU2AgPSBjb2xfbnVtYmVyKCksDQogICAgYENPTElGT1JNRVMgVE9UQUlTYCA9IGNvbF9udW1iZXIoKSwNCiAgICBDT05EVVRJVklEQURFID0gY29sX251bWJlcigpLA0KICAgIGBDUk9NTyBUT1RBTGAgPSBjb2xfbnVtYmVyKCksDQogICAgYERFTUFOREEgQklPUVXDjU1JQ0EgREUgT1hJR8OKTklPYCA9IGNvbF9udW1iZXIoKSwNCiAgICBgREVNQU5EQSBRVcONTUlDQSBERSBPWElHw4pOSU9gID0gY29sX251bWJlcigpLA0KICAgIGBFU0NIRVJJQ0hJQSBDT0xJYCA9IGNvbF9udW1iZXIoKSwNCiAgICBGRVJSTyA9IGNvbF9udW1iZXIoKSwNCiAgICBgRklUT1BMQU5DVE9OICAtIENJQU5PQkFDVMOJUklBU2AgPSBjb2xfbnVtYmVyKCksDQogICAgYEZPU0ZBVE8gT1JUT2AgPSBjb2xfbnVtYmVyKCksDQogICAgYEbDk1NGT1JPIFRPVEFMYCA9IGNvbF9udW1iZXIoKSwNCiAgICBNQU5HQU7DilMgPSBjb2xfbnVtYmVyKCksDQogICAgYE1FUkPDmlJJTyBFTSBNSUNST0dSQU1BIFBPUiBMSVRSTyAoVUcvTClgID0gY29sX251bWJlcigpLA0KICAgIE7DjVFVRUwgPSBjb2xfbnVtYmVyKCksDQogICAgTklUUkFUTyA9IGNvbF9udW1iZXIoKSwNCiAgICBgTklUUk9Hw4pOSU8gQU1PTklBQ0FMYCA9IGNvbF9udW1iZXIoKSwNCiAgICBgTklUUk9Hw4pOSU8gT1JHw4JOSUNPYCA9IGNvbF9udW1iZXIoKSwNCiAgICBgTklUUk9Hw4pOSU8gVE9UQUwgS0pFTERBSExgID0gY29sX251bWJlcigpLA0KICAgIGBPWElHw4pOSU8gRElTU09MVklET2AgPSBjb2xfbnVtYmVyKCksDQogICAgUEggPSBjb2xfbnVtYmVyKCksDQogICAgYFBST0ZVTkRJREFERSBDT0xFVEFgID0gY29sX251bWJlcigpLA0KICAgIGBQUk9GVU5ESURBREUgVE9UQUxgID0gY29sX251bWJlcigpLA0KICAgIFNBTElOSURBREUgPSBjb2xfbnVtYmVyKCksDQogICAgYFPDk0xJRE9TIERJU1NPTFZJRE9TIFRPVEFJU2AgPSBjb2xfbnVtYmVyKCksDQogICAgYFPDk0xJRE9TIFNVU1BFTlNPUyBUT1RBSVNgID0gY29sX251bWJlcigpLA0KICAgIGBTw5NMSURPUyBUT1RBSVNgID0gY29sX251bWJlcigpLA0KICAgIGBURU1QRVJBVFVSQSBEQSDDgUdVQWAgPSBjb2xfbnVtYmVyKCksDQogICAgYFRFTVBFUkFUVVJBIERPIEFSYCA9IGNvbF9udW1iZXIoKSwNCiAgICBgVFJBTlNQQVLDik5DSUEgREEgw4FHVUFgID0gY29sX251bWJlcigpLA0KICAgIFRVUkJJREVaID0gY29sX251bWJlcigpLA0KICAgIGBWQVrDg08gUkVDVVJTTyBIw41EUklDT2AgPSBjb2xfbnVtYmVyKCksDQogICAgWklOQ08gPSBjb2xfbnVtYmVyKCkNCiAgKSwNCiAgbG9jYWxlID0gbG9jYWxlKA0KICAgIGRhdGVfbmFtZXMgPSAicHQiLCANCiAgICBkZWNpbWFsX21hcmsgPSAiLCIsDQogICAgZ3JvdXBpbmdfbWFyayA9ICIiDQogICksDQogIHRyaW1fd3MgPSBUUlVFDQopICU+JQ0KICBqYW5pdG9yOjpjbGVhbl9uYW1lcygpICU+JQ0KICBzbGljZSgNCiAgICAxOihuKCkgLSA4KSAjcmV0aXJhbmRvIGFzIHVsdGltYXMgOCBsaW5oYXMNCiAgKSAlPiUgDQogIHJlbmFtZSgNCiAgICBlX2NvbGkgPSBlc2NoZXJpY2hpYV9jb2xpLA0KICAgIGRibyA9IGRlbWFuZGFfYmlvcXVpbWljYV9kZV9veGlnZW5pbywNCiAgICBtZXJjdXJpbyA9IG1lcmN1cmlvX2VtX21pY3JvZ3JhbWFfcG9yX2xpdHJvX3VnX2wNCiAgKSAlPiUNCiAgbXV0YXRlKA0KICAgIG11bmljaXBpbyA9IHN0cl90b190aXRsZShtdW5pY2lwaW8pLA0KICAgIGRhdGFfY29sZXRhID0geW1kKGRhdGFfY29sZXRhKSwNCiAgICBhbm9fY29sZXRhID0geWVhcihkYXRhX2NvbGV0YSksDQogICkgJT4lDQogIGRwbHlyOjpzZWxlY3QoICNyZW9yZGVuYW5kbyBhcyBjb2x1bmFzDQogICAgYygxOjEwKSwNCiAgICBhbm9fY29sZXRhLA0KICAgIGV2ZXJ5dGhpbmcoKQ0KICApDQpgYGANCg0KYGBge3IgSW1wb3J0YW5kbyBvcyBkYWRvc30NCnBsYW5fbGl0b3JhbF9tZWRpb19hbHRlcmFyIDwtIHJlYWRfZXhjZWwoDQogICJDOi9Vc2Vycy9Mw6lvL0Rvd25sb2Fkcy9wbGFuX2xpdG9yYWxfbWVkaW8ueGxzIiwgI2FsdGVyYWNhb18xDQogIHNoZWV0ID0gIkRhZG9zX0FqdXN0YWRvcyIsIA0KICBjb2xfdHlwZXMgPSBjKA0KICAgICJudW1lcmljIiwgInRleHQiLCAibnVtZXJpYyIsICJudW1lcmljIiwgInRleHQiLCANCiAgICAidGV4dCIsICJ0ZXh0IiwgInRleHQiLCAidGV4dCIsICJkYXRlIiwgDQogICAgImRhdGUiLCAidGV4dCIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiAgICAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiAgICAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiAgICAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiAgICAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiAgICAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiAgICAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiAgICAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiAgICAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiAgICAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiAgICAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiAgICAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiAgICAibnVtZXJpYyIsICJudW1lcmljIiwgIm51bWVyaWMiLCANCiAgICAibnVtZXJpYyIpLA0KICByYW5nZSA9ICJBMTpBWTk5IiwgI2FsdGVyYWNhb18yDQogIHRyaW1fd3MgPSBUUlVFDQopICU+JSANCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUgDQogIHJlbmFtZSgNCiAgICBlX2NvbGkgPSBlc2NoZXJpY2hpYV9jb2xpLA0KICAgIGRibyA9IGRlbWFuZGFfYmlvcXVpbWljYV9kZV9veGlnZW5pbywNCiAgICBtZXJjdXJpbyA9IG1lcmN1cmlvX2VtX21pY3JvZ3JhbWFfcG9yX2xpdHJvX3VnX2wNCiAgKSAlPiUgDQogIG11dGF0ZSgNCiAgICBtdW5pY2lwaW8gPSBzdHJfdG9fdGl0bGUobXVuaWNpcGlvKSwNCiAgICBkYXRhX2NvbGV0YSA9IHltZChkYXRhX2NvbGV0YSksDQogICAgYW5vX2NvbGV0YSA9IHllYXIoZGF0YV9jb2xldGEpLA0KICAgICMgaG9yYV9jb2xldGEgPSBwYXJzZV9kYXRldGltZShob3JhX2NvbGV0YSksDQogICkgJT4lDQogIGRwbHlyOjpzZWxlY3QoICNyZW9yZGVuYW5kbyBhcyBjb2x1bmFzDQogICAgYygxOjEwKSwNCiAgICBhbm9fY29sZXRhLA0KICAgIGV2ZXJ5dGhpbmcoKQ0KICApDQpgYGANCg0KIyBTdW3DoXJpb3MgZXN0YXTDrXN0aWNvcyB7I3NlYy1zdW3DoXJpb3MtZXN0YXTDrXN0aWNvc30NCg0KYGBge3Igc3VtYXJpbywgZWNobyA9IFRSVUV9DQpzdW1hcmlvIDwtIHBsYW5fbGl0b3JhbF9tZWRpbyAlPiUNCiAgZHBseXI6OnNlbGVjdChjb2RfZXN0YWNhbywgb3hpZ2VuaW9fZGlzc29sdmlkbywgYW5vX2NvbGV0YSkgJT4lDQogIGZpbHRlcihhbm9fY29sZXRhID4gIjIwMTMiICYNCiAgICAgICAgICAgYW5vX2NvbGV0YSA8PSAiMjAyNSIpICU+JQ0KICBncm91cF9ieShjb2RfZXN0YWNhbykgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBtaW4gPQ0KICAgICAgbWluKG94aWdlbmlvX2Rpc3NvbHZpZG8sDQogICAgICAgICAgbmEucm0gPSBUUlVFKSwNCiAgICBxMSA9DQogICAgICBxdWFudGlsZShveGlnZW5pb19kaXNzb2x2aWRvLCAwLjI1LA0KICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFKSwNCiAgICBtZWRpYW4gPQ0KICAgICAgbWVkaWFuKG94aWdlbmlvX2Rpc3NvbHZpZG8sDQogICAgICAgICAgICAgbmEucm0gPSBUUlVFKSwNCiAgICBtZWFuID0NCiAgICAgIG1lYW4ob3hpZ2VuaW9fZGlzc29sdmlkbywNCiAgICAgICAgICAgbmEucm09IFRSVUUpLA0KICAgIHEzID0NCiAgICAgIHF1YW50aWxlKG94aWdlbmlvX2Rpc3NvbHZpZG8sIDAuNzUsDQogICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUpLA0KICAgIG1heCA9DQogICAgICBtYXgob3hpZ2VuaW9fZGlzc29sdmlkbywNCiAgICAgICAgICBuYS5ybSA9IFRSVUUpKQ0KDQpzdW1hcmlvDQpgYGANCg0KIyMgVmlzdWFsaXphw6fDo28gZGEgZXN0cnV0dXJhIGRlIGRhZG9zIGRhIHBsYW5pbGhhIHsjc2VjLXZpc3VhbGl6YcOnw6NvLWRhLWVzdHJ1dHVyYS1kZS1kYWRvcy1kYS1wbGFuaWxoYX0NCg0KQ29uZmVyaXIgc2UgbyB0aXBvIGRvcyBkYWRvcyBlc3TDoSBjb3JyZXRvLCBkYXRhIGVtIGZvcm1hdG8gZGUgZGF0YSAoZGF0ZS9kdHRtKSwgY8OzZGlnbyBkYSBlc3Rhw6fDo28gY29tbyBjaGFyYWN0ZXIgKGNociksIHZhbG9yIG1lZGlkbyBkb3MgcGFyw6JtZXRyb3MgY29tbyBkb3VibGUgKGRibCkuDQoNCmBgYHtyIGVzdHJ1dHVyYSBkYSBwbGFuaWxoYSx9DQpnbGltcHNlKHBsYW5fbGl0b3JhbF9tZWRpbykNCiMgc3RyKHBsYW5fbGl0b3JhbF9tZWRpbykgI291dHJhIG1hbmVpcmEgZGUgdmlzdWFsaXphciBhIGVTVFJ1dHVyYSANCmBgYA0KDQpgYGB7ciBWaXN1YWxpemHDp8OjbyBkYSBwbGFuaWxoYSBpbXBvcnRhZGEsIGVjaG8gPSBGQUxTRX0NCnBhZ2VkX3RhYmxlKHBsYW5fbGl0b3JhbF9tZWRpbywNCiAgICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHJvd3MucHJpbnQgPSAxNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbHMucHJpbnQgPSAxMCkpDQpgYGANCg0KIyBSZXF1aXNpdG9zIHByYSBnZXJhciBvcyBncsOhZmljb3MgeyNzZWMtcmVxdWlzaXRvcy1wcmEtZ2VyYXItb3MtZ3LDoWZpY29zfQ0KDQojIyBEZWZpbmlyIG8gKnRoZW1lKg0KDQpEZWZpbmluZG8gdW1hIGNvciBkZSBsZXRyYSBlIGRlIGZ1bmRvIHBhZHLDo28gYSBzZXIgYWRvdGFkYSBub3MgZ3LDoWZpY29zLg0KDQpgYGB7ciBzZXR0aW5nIHRoZW1lfQ0KdGhlbWVfZ3JhZnMgPC0gZnVuY3Rpb24oYmcgPSAid2hpdGUiLCANCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yYWNhb19sZXRyYSA9ICJibGFjayIpIHsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IA0KICAgICAgZWxlbWVudF90ZXh0KA0KICAgICAgICBoanVzdCA9IDAuNSwNCiAgICAgICAgY29sb3IgPSBjb2xvcmFjYW9fbGV0cmEsDQogICAgICAgIHNpemUgPSAxOSksDQogICAgDQogICAgYXhpcy50aXRsZS54ID0gDQogICAgICAjIGVsZW1lbnRfdGV4dCgNCiAgICAgICMgY29sb3IgPSBjb2xvcmFjYW9fbGV0cmEsDQogICAgICAjIHNpemUgPSAxNSwNCiAgICAgICMgYW5nbGUgPSAwLCksDQogICAgICBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KA0KICAgICAgY29sb3IgPSBjb2xvcmFjYW9fbGV0cmEsDQogICAgICBzaXplID0gMTUsDQogICAgICBhbmdsZSA9IDkwKSwNCiAgICANCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dCgNCiAgICAgIGNvbG9yID0gY29sb3JhY2FvX2xldHJhLA0KICAgICAgc2l6ZSA9IDE3KSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dCgNCiAgICAgIGNvbG9yID0gY29sb3JhY2FvX2xldHJhLA0KICAgICAgc2l6ZSA9IDE3LA0KICAgICAgYW5nbGUgPSAwKSwNCiAgICANCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSBiZywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gMSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAwLjUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpLA0KICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE3KSwNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSBiZyksDQogICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSBiZyksDQogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4obCA9IDUsIHIgPSAxMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICBiID0gNSwgdCA9IDUpDQogICkNCn0NCmBgYA0KDQojIyBDcmlhciBmdW7Dp8OjbyBwYXJhIGdlcmFyIGJveHBsb3RzIGNvbSBwZXJjZW50aXMgMjAgZSA4MA0KDQpgYGB7ciBmdW5jYW8gcGVyY2VudGlsIDIwIGUgODB9DQpmIDwtIGZ1bmN0aW9uKHgpIHsNCiAgciA8LSBxdWFudGlsZSh4LCBwcm9icyA9IGMoMC4xMCwgMC4yMCwgMC41MCwgMC44MCwgMC45MCkpDQogIG5hbWVzKHIpIDwtIGMoInltaW4iLCAibG93ZXIiLCAibWlkZGxlIiwgInVwcGVyIiwgInltYXgiKQ0KICByZXR1cm4ocikNCn0NCmBgYA0KDQojIEdyw6FmaWNvcyB7I3NlYy1ncsOhZmljb3MgLmdyYWZpY29zfQ0KDQo+ICoqQXRlbsOnw6NvOioqIFRvbWFyIG11aXRvIGN1aWRhZG8gY29tIGEgb3JkZW0gcXVlIGVzdMOjbyBkaXNwb3N0YXMgYXMgZXN0YcOnw7Vlcy4gRGV2ZS1zZSBzZW1wcmUgcmVzcGVpdGFyIG8gc2VudGlkbyBuYXNjZW50ZSAtXD4gZm96Lg0KPg0KPiBDb25mZXJpciBhIG9yZGVtIGRhcyBlc3Rhw6fDtWVzIGF0cmF2w6lzIGRvIFttYXBhIGludGVyYXRpdm9dKCNzZWMtbWFwYS1pbnRlcmF0aXZvLWNvbS1sb2NhbGl6YcOnw6NvLWRvcy1wb250b3MtZGUtbW9uaXRvcmFtZW50bykuDQo+DQo+IEVsYXMgYWNhYmFtIGZpY2FuZG8gZm9yYSBkZSBvcmRlbSBwb3IgY29udGEgZG8gY8OzZGlnbyBkZSBvdHRvYmFjaWFzIFBhcmEgcmVvcmRlbmFyIGFzIGVzdGHDp8O1ZXMsIGF0ZW50ZS1zZSDDoCBmdW7Dp8OjbyBgc2NhbGVfeF9kaXNjcmV0ZWAgZGVzY3JpdG8gbm8gY29kZSBjaHVuayBhYmFpeG86DQoNCmBgYHtyIHJlb3JkZW5hciBlc3Rhw6fDtWVzIG5vIGdyw6FmaWNvLCBldmFsID0gRkFMU0V9DQpzY2FsZV94X2Rpc2NyZXRlKA0KICBsaW1pdHMgPSBjKA0KICAgICI4NzMzMjUwMCIsDQogICAgIjg3NDIwMTMwIiwNCiAgICAiODc0MjAxNTAiLA0KICAgICI4NzQyMDM1MCIsDQogICAgIjg3NDIwNTAwIiwNCiAgICAiODc1MTAwMTAiDQogICksDQogIGxhYmVscyA9IGMoDQogICAgIlBNMSIsICJQTTIiLCAiUE0zIiwgIlBNNCIsICJQTTUiLCAiUE02Ig0KICApDQopKw0KYGBgDQoNCk9iczogUGFyYSBhIEJhY2lhIEhpZHJvZ3LDoWZpY2EgZG8gUmlvIEdyYXZhdGHDrSDDqSBuZWNlc3PDoXJpbw0KDQo+IFNlbXByZSB0b21hciBjdWlkYWRvIGNvbSBvcyBsaW1pdGVzIGRvICoqZWl4byB5KiouIERlaXhlaSBjb21vIHBhZHLDo28gbyBSIGJ1c2NhciBhdXRvbWF0aWNhbWVudGUgcXVhbCBvIHZhbG9yIG3DrW5pbW8gZSBtw6F4aW1vIGRhcXVlbGUgcGFyw6JtZXRybywgbWFzIG8gaWRlYWwgw6kgcXVlIHNlIGFqdXN0ZSBjYXNvIGEgY2Fzby4NCg0KQ2FzbyBxdWVpcmEgYWx0ZXJhciBvIHRhbWFuaG8gZG9zIG91dGxpZXJzLCBhbHRlcmFyIG8gYHNpemVgIG5lc3NlIHRyZWNobyBkb3MgY8OzZGlnb3M6DQoNCmBgYHtyIGFsdGVyYXIgdGFtYW5obyBkbyBvdXRsaWVyLCBldmFsID0gRkFMU0V9DQpnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKA0KICAgICAjIGdyb3Vwb25YID0gRkFMU0UsDQogICAgIHNpemUgPSAxLjIsIA0KICAgICBhbHBoYSA9IC4yNSwNCiAgICAgd2lkdGggPSAuMDcsDQogICApKw0KYGBgDQoNCj4gVG9kb3Mgb3MgZ3LDoWZpY29zIGZvcmFtIGdlcmFkb3MgdXRpbGl6YW5kbyBjb21vIHBhZHLDo28gb3MgbGltaXRlcyBkYSBSZXNvbHXDp8OjbyBuwrogMzU3LzA1IGRvIENPTkFNQSBwYXJhIGFtYmllbnRlcyAqKmzDs3RpY29zKiouIENhc28gcXVlaXJhIGFsdGVyYXIgb3MgbGltaXRlcyBwYXJhIGFkZXF1YXIgYW9zIGFtYmllbnRlcyAqKmzDqm50aWNvcyoqLCBkZXZlLXNlIGVkaXRhciBvcyBgeW1pbmAgZSBgeW1heGAgZGUgY2FkYSByZXTDom5ndWxvIChgcmVjdGApIGRvIHJlZmVyaWRvIHBhcsOibWV0cm8uDQo+DQo+IE7Do28gZXNxdWVjZXIgcXVlIG8gUiBlbnRlbmRlIGEgY2FzYSBkZWNpbWFsIGNvbW8gcG9udG8sIGUgbsOjbyBjb21vIHbDrXJndWxhLg0KDQpgYGB7ciBhbWJpZW50ZSBsw7N0aWNvIHggbMOqbnRpY28sIGV2YWwgPSBGQUxTRX0NCmFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgeW1pbiA9IDEzLjMsIHltYXggPSBJbmYsDQogICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICBmaWxsID0gIiNhYzUwNzkiKSsgIz5waW9yIGNsYXNzZQ0KYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICB5bWluID0gMy43LCB5bWF4ID0gMTMuMywNCiAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgIGZpbGwgPSAiI2ZjZjdhYiIpKyAjY2xhc3NlIDMNCmFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgeW1pbiA9IDAsIHltYXggPSAzLjcsDQogICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICBmaWxsID0gIiM4ZGNkZWIiKSsgI2NsYXNzZSAxDQpgYGANCg0KIyMgUGFyw6JtZXRyb3MgZGUgUXVhbGlkYWRlIGRhIMOBZ3VhIHsjc2VjLXBhcsOibWV0cm9zLWRlLXF1YWxpZGFkZS1kYS3DoWd1YX0NCg0KIyMjIE94aWfDqm5pbyBEaXNzb2x2aWRvIHsjc2VjLW94aWfDqm5pby1kaXNzb2x2aWRvfQ0KDQpgYGB7ciBHcsOhZmljbyBPRCwgZmlnLmNhcD0iT3hpZ8OqbmlvIERpc3NvbHZpZG8iLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBmb2xkLnBsb3Q9RkFMU0V9DQooZ3JhZl9vZCA8LSBwbGFuX2xpdG9yYWxfbWVkaW8gJT4lDQogICBnZ3Bsb3QoDQogICAgIGFlcygNCiAgICAgICB4ID0gY29kX2VzdGFjYW8sDQogICAgICAgeSA9IG94aWdlbmlvX2Rpc3NvbHZpZG8sDQogICAgICkNCiAgICkrDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSAtSW5mLCB5bWF4ID0gMiwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2FjNTA3OSIpKyAjPnBpb3IgY2xhc3NlDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSAyLCB5bWF4ID0gNCwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2ViNTY2MSIpKyAjY2xhc3NlIDQNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDQsIHltYXggPSA1LA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjZmNmN2FiIikrICNjbGFzc2UgMw0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gNSwgeW1heCA9IDYsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiM3MGMxOGMiKSsgI2NsYXNzZSAyDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW49IDYsIHltYXggPSBJbmYsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiM4ZGNkZWIiKSsgI2NsYXNzZSAxDQogICBzdGF0X2JveHBsb3QoDQogICAgIGZ1bi5kYXRhID0gZiwNCiAgICAgZ2VvbSA9ICdlcnJvcmJhcicsDQogICAgIHdpZHRoID0gMC4zLA0KICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSksDQogICApKw0KICAgc3RhdF9ib3hwbG90KA0KICAgICBmdW4uZGF0YSA9IGYsDQogICAgIHdpZHRoID0gMC43LA0KICAgICBmaWxsID0gJyNGOEY4RkYnLA0KICAgICBjb2xvciA9ICJibGFjayIsDQogICAgIGdlb20gPSAiYm94cGxvdCIsDQogICAgIG91dGxpZXIuc2hhcGUgPSAxLCAjc2UgZGVpeGFyIE5BIGZpY2Egc8OzIG8gaml0dGVyLCBzZSBuw6NvLCBkZWl4YSAxDQogICApKw0KICAgIyBmYWNldF93cmFwKH5wZXJpb2RvKSsNCiAgIGxhYnMoDQogICAgIHRpdGxlID0gIk94aWfDqm5pbyBEaXNzb2x2aWRvIiwNCiAgICAgeD0gTlVMTCwNCiAgICAgeT0ibWcvTCINCiAgICkrDQogICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKA0KICAgICBzaXplID0gMS4yLA0KICAgICBhbHBoYSA9IC4yNSwNCiAgICAgd2lkdGggPSAuMDcsDQogICApKw0KICAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwwKSksDQogICAgIG4uYnJlYWtzID0gMTEsDQogICAgICMgbGltaXRzID0gYygtMC4zLDIxKQ0KICAgICBsaW1pdHMgPSBjKA0KICAgICAgIG1pbihwbGFuX2xpdG9yYWxfbWVkaW8kb3hpZ2VuaW9fZGlzc29sdmlkbywgbmEucm0gPSBUUlVFKSwNCiAgICAgICBtYXgocGxhbl9saXRvcmFsX21lZGlvJG94aWdlbmlvX2Rpc3NvbHZpZG8sIG5hLnJtID0gVFJVRSkrMSkNCiAgICkrDQogICAjIHNjYWxlX3hfZGlzY3JldGUoDQogICAjICAgbGltaXRzID0gYygNCiAgICMgICAgICI4NzMzMjUwMCIsDQogICAjICAgICAiODc0MjAxMzAiLA0KICAgIyAgICAgIjg3NDIwMTUwIiwNCiAgICMgICAgICI4NzQyMDM1MCIsDQogICAjICAgICAiODc0MjA1MDAiLA0KICAgIyAgICAgIjg3NTEwMDEwIg0KICAgIyAgICksDQogICAjICAgbGFiZWxzID0gYygNCiAgICMgICAgICJQTTEiLCAiUE0yIiwgIlBNMyIsICJQTTQiLCAiUE01IiwgIlBNNiINCiAgICMgICApDQogICAjICkrDQogICBnZW9tX3Ntb290aCgNCiAgICAgbWV0aG9kID0gImxtIiwNCiAgICAgc2UgPSBGQUxTRSwgI3NlIGRlaXhhciBUUlVFIGdlcmEgbyBpbnRlcnZhbG8gZGUgY29uZmlhbsOnYSBkZSA5NSUNCiAgICAgYWVzKGdyb3VwID0gMSksDQogICAgIGFscGhhID0gMC41LA0KICAgICBuYS5ybSA9IFRSVUUsDQogICAgIHNpemUgPSAxDQogICApKw0KICAgdGhlbWVfZ3JhZnMoKQ0KKQ0KYGBgDQoNCiMjIyBEQk8geyNzZWMtZGJvfQ0KDQpgYGB7ciBHcsOhZmljbyBEQk8sIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCBmaWcuY2FwPSJEZW1hbmRhIEJpb3F1w61taWNhIGRlIE94aWfDqm5pbyIsIGZvbGQucGxvdD1GQUxTRX0NCihncmFmX2RibyA8LSBnZ3Bsb3QocGxhbl9saXRvcmFsX21lZGlvLA0KICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IGNvZF9lc3RhY2FvLA0KICAgICAgICAgICAgICAgICAgIHkgPSBkYm8pKSsNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDEwLCB5bWF4ID0gSW5mLA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjYWM1MDc5IikrICM+cGlvciBjbGFzc2UNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDUsIHltYXggPSAxMCwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2ZjZjdhYiIpKyAjY2xhc3NlIDMNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDMsIHltYXggPSA1LA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjNzBjMThjIikrICNjbGFzc2UgMg0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gMCwgeW1heCA9IDMsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiM4ZGNkZWIiKSsgI2NsYXNzZSAxDQogICBzdGF0X2JveHBsb3QoDQogICAgICBnZW9tID0gJ2Vycm9yYmFyJywNCiAgICAgIHdpZHRoID0gMC4zLA0KICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNjUpLA0KICAgICAgZnVuLmRhdGEgPSBmLA0KICAgICkrDQogICAgc3RhdF9ib3hwbG90KA0KICAgICAgd2lkdGggPSAwLjcsDQogICAgICBmaWxsID0gJyNGOEY4RkYnLA0KICAgICAgY29sb3IgPSAiYmxhY2siLA0KICAgICAgZnVuLmRhdGEgPSBmLA0KICAgICAgZ2VvbSA9ICJib3hwbG90IiwNCiAgICAgIG91dGxpZXIuc2hhcGUgPSAxLCAjc2UgZGVpeGFyIE5BIGZpY2Egc8OzIG8gaml0dGVyLCBzZSBuw6NvLCBkZWl4YSAxDQogICAgKSsNCiAgICMgZmFjZXRfd3JhcCh+cGVyaW9kbykrDQogICBsYWJzKHRpdGxlID0gIkRlbWFuZGEgQmlvcXXDrW1pY2EgZGUgT3hpZ8OqbmlvIiwNCiAgICAgICAgeD0iRXN0YcOnw6NvIiwNCiAgICAgICAgeT0ibWcvTCIpKw0KICAgZ2diZWVzd2FybTo6Z2VvbV9xdWFzaXJhbmRvbSgNCiAgICAgIyBncm91cG9uWCA9IEZBTFNFLA0KICAgICBzaXplID0gMS4yLA0KICAgICBhbHBoYSA9IC4yNSwNCiAgICAgd2lkdGggPSAuMDcsDQogICApKw0KICAgIyBzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IGMoIjg3Mzk4NTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5ODAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODkwMCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTUwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDU1MDAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwNjkwMCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA5OTAwIiksDQogICAjICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiUE0xIiwgIlBNMiIsICJQTTMiLCAiUE00IiwgIlBNNSIsICJQTTYiLCAiUE03IikNCiAgICMgKSsNCiAgIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMC4wMywwLjAzKSksDQogICAgICAgICAgICAgICAgICAgICAgbi5icmVha3MgPSA4LA0KICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoDQogICAgICAgICAgICAgICAgICAgICAgICBtaW4ocGxhbl9saXRvcmFsX21lZGlvJGRibywgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIDEwDQogICAgICAgICAgICAgICAgICAgICAgICAjIG1heChwbGFuX2xpdG9yYWxfbWVkaW8kZGJvLCBuYS5ybSA9IFRSVUUpDQogICAgICAgICAgICAgICAgICAgICAgICApLA0KICAgICAgICAgICAgICAgICAgICAgIHRyYW5zID0gImxvZzEwIikrDQogICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLA0KICAgICAgICAgICAgICAgc2U9RkFMU0UsICNzZSBkZWl4YXIgVFJVRSBnZXJhIG8gaW50ZXJ2YWxvIGRlIGNvbmZpYW7Dp2EgZGUgOTUlDQogICAgICAgICAgICAgICBhZXMoZ3JvdXA9MSksDQogICAgICAgICAgICAgICBhbHBoYT0uNSwNCiAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRSwNCiAgICAgICAgICAgICAgIHNpemUgPSAxKSsNCiAgIHRoZW1lX2dyYWZzKCkNCikNCmBgYA0KDQojIyMgKkVzY2hlcmljaGlhIGNvbGkqDQoNCmBgYHtyIEdyw6FmaWNvIEVjb2xpLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgZmlnLmNhcD0iRXNjaGVyaWNoaWEtY29saSIsIGZvbGQucGxvdD1GQUxTRX0NCihncmFmX2Vjb2xpIDwtIHBsYW5fbGl0b3JhbF9tZWRpbyAlPiUgDQogICBnZ3Bsb3QoYWVzKGNvZF9lc3RhY2FvLA0KICAgICAgICAgICAgICBlX2NvbGkpKSsNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDMyMDAsIHltYXggPSBJbmYsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiNhYzUwNzkiKSsgIz5waW9yIGNsYXNzZQ0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gODAwLCB5bWF4ID0gMzIwMCwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2ZjZjdhYiIpKyAjY2xhc3NlIDMNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDE2MCwgeW1heCA9IDgwMCwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiIzcwYzE4YyIpKyAjY2xhc3NlIDINCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDAsIHltYXggPSAxNjAsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiM4ZGNkZWIiKSsgI2NsYXNzZSAxDQogICBzdGF0X2JveHBsb3QoZ2VvbSA9ICdlcnJvcmJhcicsDQogICAgICAgICAgICAgICAgd2lkdGg9MC4zLA0KICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSkrDQogICBnZW9tX2JveHBsb3QoZmlsbD0nI0Y4RjhGRicsDQogICAgICAgICAgICAgICAgY29sb3I9ImJsYWNrIiwNCiAgICAgICAgICAgICAgICBvdXRsaWVyLnNoYXBlID0gMSwgI3NlIGRlaXhhciBOQSBmaWNhIHPDsyBvIGppdHRlciwgc2UgbsOjbywgZGVpeGEgMQ0KICAgICAgICAgICAgICAgIHdpZHRoPSAwLjcpKw0KICAgIyBmYWNldF93cmFwKH5wZXJpb2RvKSsNCiAgIGxhYnModGl0bGUgPSAiKkVzY2hlcmljaGlhIGNvbGkqIiwNCiAgICAgICAgeD0iRXN0YcOnw6NvIiwNCiAgICAgICAgeT0iTk1QLzEwMG1MIikrDQogICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAuMDEsIDAuMDEpKSwNCiAgICAgICAgICAgICAgICAgICAgICAjIG4uYnJlYWtzID0gOSwNCiAgICAgICAgICAgICAgICAgICAgICBuLmJyZWFrcyA9IDYsDQogICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYyhtaW4ocGxhbl9saXRvcmFsX21lZGlvJGVfY29saSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChwbGFuX2xpdG9yYWxfbWVkaW8kZV9jb2xpLCBuYS5ybSA9IFRSVUUpKSwNCiAgICAgICAgICAgICAgICAgICAgICB0cmFucyA9ICJsb2cxMCIsDQogICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjpudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjaW1hbC5tYXJrID0gIiwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaWcubWFyayA9ICIgIikpKw0KICAgZ2diZWVzd2FybTo6Z2VvbV9xdWFzaXJhbmRvbSgNCiAgICAgc2l6ZSA9IDEuMiwNCiAgICAgYWxwaGEgPSAuMjUsDQogICAgIHdpZHRoID0gLjA3LA0KICAgKSsNCiAjIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gYygiODczOTg1MDAiLA0KICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODk4MCIsDQogIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTAwIiwNCiAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5NTAiLA0KICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwNTUwMCIsDQogIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA2OTAwIiwNCiAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDk5MDAiKSwNCiAjICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiUE0xIiwgIlBNMiIsICJQTTMiLCAiUE00IiwgIlBNNSIsICJQTTYiLCAiUE03IikNCiAjICkrDQogZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwNCiBzZT1GQUxTRSwgI3N0YXJkYW5kIGVycm9yID0gZGVzdmlvIHBhZHLDo28gLT4gc2UgZGVpeGFyIFRSVUUgZ2VyYSBvIGludGVydmFsbyBkZSBjb25maWFuw6dhIGRlIDk1JQ0KICAgICAgICAgICAgIGFlcyhncm91cD0xKSwNCiAgICAgICAgICAgICBhbHBoYT0gMC41LCAjdHJhbnNwYXJlbmNpYSBkZSA1MCUNCiAgICAgICAgICAgICBuYS5ybSA9IFRSVUUsICNyZW1vdmVyIE5Bcw0KICAgICAgICAgICAgIHNpemUgPSAxKSsNCiB0aGVtZV9ncmFmcygpKw0KICAgdGhlbWUoDQogICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KA0KICAgICAgIGFuZ2xlID0gOTAsDQogICAgICAgIyBzaXplPTE1LA0KICAgICAgICMgZmFjZT0yDQogICAgICksDQogICAgIHBsb3QudGl0bGUgPSANCiAgICAgICBlbGVtZW50X21hcmtkb3duKA0KICAgICAgICAgaGp1c3QgPSAwLjUsDQogICAgICAgICBjb2xvciA9ICJibGFjayIsDQogICAgICAgICBzaXplID0gMTkpLA0KICAgKQ0KKQ0KYGBgDQoNCiMjIyBGw7NzZm9ybyBUb3RhbCB7I3NlYy1mw7NzZm9yby10b3RhbH0NCg0KYGBge3IgR3LDoWZpY28gZsOzc2Zvcm8gdG90YWwsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCBmaWcuY2FwPSJGw7NzZm9ybyB0b3RhbCIsIGZvbGQucGxvdD1GQUxTRX0NCihncmFmX3B0b3QgPC0gZ2dwbG90KHBsYW5fbGl0b3JhbF9tZWRpbywNCiAgICAgICAgICAgICAgICAgICAgIGFlcyhjb2RfZXN0YWNhbywNCiAgICAgICAgICAgICAgICAgICAgICAgICBmb3Nmb3JvX3RvdGFsKSkrDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSAwLjE1LCB5bWF4ID0gSW5mLA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjYWM1MDc5IikrICM+cGlvciBjbGFzc2UNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDAuMSwgeW1heCA9IDAuMTUsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiNmY2Y3YWIiKSsgI2NsYXNzZSAzDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSAwLCB5bWF4ID0gMC4xLA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjOGRjZGViIikrICNjbGFzc2UgMQ0KICAgc3RhdF9ib3hwbG90KGdlb20gPSAnZXJyb3JiYXInLA0KICAgICAgICAgICAgICAgIHdpZHRoPTAuMywNCiAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSkpKw0KICAgZ2VvbV9ib3hwbG90KGZpbGw9JyNGOEY4RkYnLA0KICAgICAgICAgICAgICAgIGNvbG9yPSJibGFjayIsDQogICAgICAgICAgICAgICAgb3V0bGllci5zaGFwZSA9IDEsICNzZSBkZWl4YXIgTkEgZmljYSBzw7MgbyBqaXR0ZXIsIHNlIG7Do28sIGRlaXhhIDENCiAgICAgICAgICAgICAgICB3aWR0aD0gMC43KSsNCiAgICMgZmFjZXRfd3JhcCh+cGVyaW9kbykrDQogICBsYWJzKHRpdGxlID0gIkbDs3Nmb3JvIHRvdGFsIiwNCiAgICAgICAgeD0iRXN0YcOnw6NvIiwNCiAgICAgICAgeT0ibWcvTCIpKw0KICAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLjAzLDAuMDMpKSwNCiAgICAgICAgICAgICAgICAgICAgICBuLmJyZWFrcyA9IDgsDQogICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYyhtaW4ocGxhbl9saXRvcmFsX21lZGlvJGZvc2Zvcm9fdG90YWwsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgocGxhbl9saXRvcmFsX21lZGlvJGZvc2Zvcm9fdG90YWwpLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgICAgIHRyYW5zID0gImxvZzEwIiwNCiAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzY2FsZXM6Om51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAuMDAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNpbWFsLm1hcmsgPSAiLCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpZy5tYXJrID0gIiAiKQ0KICAgKSsNCiAgIGdnYmVlc3dhcm06Omdlb21fcXVhc2lyYW5kb20oDQogICAgIHNpemUgPSAxLjIsDQogICAgIGFscGhhID0gLjI1LA0KICAgICB3aWR0aCA9IC4wNywNCiAgICkrDQogICAjIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gYygiODczOTg1MDAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODk4MCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5NTAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwNTUwMCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA2OTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDk5MDAiKSwNCiAgICMgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJQTTEiLCAiUE0yIiwgIlBNMyIsICJQTTQiLCAiUE01IiwgIlBNNiIsICJQTTciKQ0KICAgIyApKw0KICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwNCiAgICAgICAgICAgICAgIHNlPUZBTFNFLCAjc2UgZGVpeGFyIFRSVUUgZ2VyYSBvIGludGVydmFsbyBkZSBjb25maWFuw6dhIGRlIDk1JQ0KICAgICAgICAgICAgICAgYWVzKGdyb3VwPTEpLA0KICAgICAgICAgICAgICAgYWxwaGE9LjUsDQogICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUsDQogICAgICAgICAgICAgICBzaXplID0gMSkrDQogICB0aGVtZV9ncmFmcygpDQopDQpgYGANCg0KIyMjIE5pdHJvZ8OqbmlvIGFtb25pYWNhbCB7I3NlYy1uaXRyb2fDqm5pby1hbW9uaWFjYWx9DQoNCmBgYHtyIEdyw6FmaWNvIE5pdHJvZ8OqbmlvIEFtb25pYWNhbCwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGZpZy5jYXA9Ik5pdHJvZ8OqbmlvIEFtb25pYWNhbCIsIGZvbGQucGxvdD1GQUxTRX0NCihncmFmX25hbW9uIDwtIGdncGxvdChwbGFuX2xpdG9yYWxfbWVkaW8sDQogICAgICAgICAgICAgICAgIGFlcyhjb2RfZXN0YWNhbywNCiAgICAgICAgICAgICAgICAgICAgIG5pdHJvZ2VuaW9fYW1vbmlhY2FsKSkrDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSAxMy4zLCB5bWF4ID0gSW5mLA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjYWM1MDc5IikrICM+cGlvciBjbGFzc2UNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDMuNywgeW1heCA9IDEzLjMsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiNmY2Y3YWIiKSsgI2NsYXNzZSAzDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSAwLCB5bWF4ID0gMy43LA0KICAgICAgICAgICAgYWxwaGEgPSAxLA0KICAgICAgICAgICAgZmlsbCA9ICIjOGRjZGViIikrICNjbGFzc2UgMQ0KICAgc3RhdF9ib3hwbG90KGdlb20gPSAnZXJyb3JiYXInLA0KICAgICAgICAgICAgICAgIHdpZHRoPTAuMywNCiAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSkpKw0KICAgZ2VvbV9ib3hwbG90KGZpbGw9JyNGOEY4RkYnLA0KICAgICAgICAgICAgICAgIGNvbG9yPSJibGFjayIsDQogICAgICAgICAgICAgICAgb3V0bGllci5zaGFwZSA9IDEsICNzZSBkZWl4YXIgTkEgZmljYSBzw7MgbyBqaXR0ZXIsIHNlIG7Do28sIGRlaXhhIDENCiAgICAgICAgICAgICAgICB3aWR0aD0gMC43KSsNCiAgICMgZmFjZXRfd3JhcCh+cGVyaW9kbykrDQogICBsYWJzKHRpdGxlID0gIk5pdHJvZ8OqbmlvIGFtb25pYWNhbCIsDQogICAgICAgIHg9IkVzdGHDp8OjbyIsDQogICAgICAgIHk9Im1nL0wiKSsNCiAgIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMC4wMSwgMC4wNSkpLA0KICAgICAgICAgICAgICAgICAgICAgIG4uYnJlYWtzID0gOSwNCiAgICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKG1pbihwbGFuX2xpdG9yYWxfbWVkaW8kbml0cm9nZW5pb19hbW9uaWFjYWwsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxNQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBtYXgocGxhbl9saXRvcmFsX21lZGlvJG5pdHJvZ2VuaW9fYW1vbmlhY2FsLCBuYS5ybSA9IFRSVUUpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLA0KICAgICAgICAgICAgICAgICAgICAgIHRyYW5zID0gImxvZzEwIiwNCiAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzY2FsZXM6Om51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAuMDAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNpbWFsLm1hcmsgPSAiLCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpZy5tYXJrID0gIiAiKSkrDQogICBnZ2JlZXN3YXJtOjpnZW9tX3F1YXNpcmFuZG9tKA0KICAgICBzaXplID0gMS4yLA0KICAgICBhbHBoYSA9IC4yNSwNCiAgICAgd2lkdGggPSAuMDcsDQogICApKw0KICAgIyBzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IGMoIjg3Mzk4NTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5ODAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODkwMCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTUwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDU1MDAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwNjkwMCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA5OTAwIiksDQogICAjICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiUE0xIiwgIlBNMiIsICJQTTMiLCAiUE00IiwgIlBNNSIsICJQTTYiLCAiUE03IikNCiAgICMgKSsNCiAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsDQogICAgICAgICAgICAgICBzZT1GQUxTRSwgI3NlIGRlaXhhciBUUlVFIGdlcmEgbyBpbnRlcnZhbG8gZGUgY29uZmlhbsOnYSBkZSA5NSUNCiAgICAgICAgICAgICAgIGFlcyhncm91cD0xKSwNCiAgICAgICAgICAgICAgIGFscGhhPS41LA0KICAgICAgICAgICAgICAgbmEucm0gPSBUUlVFLA0KICAgICAgICAgICAgICAgc2l6ZSA9IDEpKw0KICAgdGhlbWVfZ3JhZnMoKQ0KKQ0KYGBgDQoNCiMjIyBUdXJiaWRleiB7I3NlYy10dXJiaWRlen0NCg0KYGBge3IgR3LDoWZpY28gVHVyYmlkZXosIGZpZy5jYXA9InR1cmJpZGV6Iiwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGZvbGQucGxvdD1GQUxTRX0NCihncmFmX3R1cmIgPC0gZ2dwbG90KHBsYW5fbGl0b3JhbF9tZWRpbywNCiAgICAgICAgICAgICAgICAgICBhZXMoY29kX2VzdGFjYW8sDQogICAgICAgICAgICAgICAgICAgICAgIHR1cmJpZGV6KSkrDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSAxMDAsIHltYXggPSBJbmYsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiNhYzUwNzkiKSsgIz5waW9yIGNsYXNzZQ0KICAgYW5ub3RhdGUoInJlY3QiLA0KICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQogICAgICAgICAgICB5bWluID0gNDAsIHltYXggPSAxMDAsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiNmY2Y3YWIiKSsgI2NsYXNzZSAzDQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluID0gLUluZiwgeG1heCA9IEluZiwNCiAgICAgICAgICAgIHltaW4gPSAwLCB5bWF4ID0gNDAsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiM4ZGNkZWIiKSsgI2NsYXNzZSAxDQogICBzdGF0X2JveHBsb3QoZ2VvbSA9ICdlcnJvcmJhcicsDQogICAgICAgICAgICAgICAgd2lkdGg9MC4zLA0KICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSkrDQogICBnZW9tX2JveHBsb3QoZmlsbD0nI0Y4RjhGRicsDQogICAgICAgICAgICAgICAgY29sb3I9ImJsYWNrIiwNCiAgICAgICAgICAgICAgICBvdXRsaWVyLnNoYXBlID0gMSwgI3NlIGRlaXhhciBOQSBmaWNhIHPDsyBvIGppdHRlciwgc2UgbsOjbywgZGVpeGEgMQ0KICAgICAgICAgICAgICAgIHdpZHRoPSAwLjcpKw0KICAgIyBmYWNldF93cmFwKH5wZXJpb2RvKSsNCiAgIGxhYnModGl0bGUgPSAiVHVyYmlkZXoiLA0KICAgICAgICB4PSJFc3Rhw6fDo28iLA0KICAgICAgICB5PSJVTlQiKSsNCiAgIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMC4wNSwgMC4wNSkpLA0KICAgICAgICAgICAgICAgICAgICAgIG4uYnJlYWtzID0gOCwNCiAgICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKA0KICAgICAgICAgICAgICAgICAgICAgICAgIyAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgbWluKHBsYW5fbGl0b3JhbF9tZWRpbyR0dXJiaWRleiwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICMgNTAwDQogICAgICAgICAgICAgICAgICAgICAgICBtYXgocGxhbl9saXRvcmFsX21lZGlvJHR1cmJpZGV6LCBuYS5ybSA9IFRSVUUpDQogICAgICAgICAgICAgICAgICAgICAgKSwNCiAgICAgICAgICAgICAgICAgICAgICB0cmFucyA9ICJsb2cxMCIsDQogICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjpudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjaW1hbC5tYXJrID0gIiwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiaWcubWFyayA9ICIgIikpKw0KICAgIGdnYmVlc3dhcm06Omdlb21fcXVhc2lyYW5kb20oDQogICAgIHNpemUgPSAxLjIsDQogICAgIGFscGhhID0gLjI1LA0KICAgICB3aWR0aCA9IC4wNywNCiAgICkrDQogICAjIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gYygiODczOTg1MDAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODk4MCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5NTAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwNTUwMCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA2OTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDk5MDAiKSwNCiAgICMgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJQTTEiLCAiUE0yIiwgIlBNMyIsICJQTTQiLCAiUE01IiwgIlBNNiIsICJQTTciKQ0KICAgIyApKw0KICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwNCiAgICAgICAgICAgICAgIHNlPUZBTFNFLCAjc2UgZGVpeGFyIFRSVUUgZ2VyYSBvIGludGVydmFsbyBkZSBjb25maWFuw6dhIGRlIDk1JQ0KICAgICAgICAgICAgICAgYWVzKGdyb3VwPTEpLA0KICAgICAgICAgICAgICAgYWxwaGE9LjUsDQogICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUsDQogICAgICAgICAgICAgICBzaXplID0gMSkrDQogICB0aGVtZV9ncmFmcygpDQopDQpgYGANCg0KIyMjIHBIIHsjc2VjLXBIfQ0KDQpgYGB7ciBHcsOhZmljbyBwSCwgZmlnLmNhcD0icEgiLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgZm9sZC5wbG90PUZBTFNFfQ0KKGdyYWZfcEggPC0gZ2dwbG90KHBsYW5fbGl0b3JhbF9tZWRpbywNCiAgICAgICAgICAgICAgICAgYWVzKGNvZF9lc3RhY2FvLA0KICAgICAgICAgICAgICAgICAgICAgcGgpKSsNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW49LUluZiwNCiAgICAgICAgICAgIHhtYXg9SW5mLA0KICAgICAgICAgICAgeW1pbj0tSW5mLA0KICAgICAgICAgICAgeW1heD02LA0KICAgICAgICAgICAgYWxwaGE9MSwNCiAgICAgICAgICAgIGZpbGw9IiNlYjU2NjEiKSsgI2NsYXNzZSA0DQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluPS1JbmYsDQogICAgICAgICAgICB4bWF4PUluZiwNCiAgICAgICAgICAgIHltaW49OSwNCiAgICAgICAgICAgIHltYXg9SW5mLA0KICAgICAgICAgICAgYWxwaGE9MSwNCiAgICAgICAgICAgIGZpbGw9IiNlYjU2NjEiKSsgI2NsYXNzZSA0DQogICBhbm5vdGF0ZSgicmVjdCIsDQogICAgICAgICAgICB4bWluPS1JbmYsDQogICAgICAgICAgICB4bWF4PUluZiwNCiAgICAgICAgICAgIHltaW49NiwNCiAgICAgICAgICAgIHltYXg9OSwNCiAgICAgICAgICAgIGFscGhhPTEsDQogICAgICAgICAgICBmaWxsPSIjOGRjZGViIikrICNjbGFzc2UgMQ0KICAgc3RhdF9ib3hwbG90KGdlb20gPSAnZXJyb3JiYXInLA0KICAgICAgICAgICAgICAgIHdpZHRoPTAuMywNCiAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC42NSkpKw0KICAgZ2VvbV9ib3hwbG90KGZpbGw9JyNGOEY4RkYnLA0KICAgICAgICAgICAgICAgIGNvbG9yPSJibGFjayIsDQogICAgICAgICAgICAgICAgb3V0bGllci5zaGFwZSA9IDEsICNzZSBkZWl4YXIgTkEgZmljYSBzw7MgbyBqaXR0ZXIsIHNlIG7Do28sIGRlaXhhIDENCiAgICAgICAgICAgICAgICB3aWR0aD0gMC43KSsNCiAgICMgZmFjZXRfd3JhcCh+cGVyaW9kbykrDQogICBsYWJzKHRpdGxlID0gInBIIiwNCiAgICAgICAgeD0iRXN0YcOnw6NvIiwNCiAgICAgICAgeT0iIikrDQogICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAuMDEsIDAuMDEpKSwNCiAgICAgICAgICAgICAgICAgICAgICBuLmJyZWFrcyA9IDgsDQogICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYyg0LDExKSwNCiAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzY2FsZXM6Om51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNpbWFsLm1hcmsgPSAiLCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpZy5tYXJrID0gIiAiKQ0KICAgICAgICAgICAgICAgICAgICAgICkrDQogICAgZ2diZWVzd2FybTo6Z2VvbV9xdWFzaXJhbmRvbSgNCiAgICAgc2l6ZSA9IDEuMiwNCiAgICAgYWxwaGEgPSAuMjUsDQogICAgIHdpZHRoID0gLjA3LA0KICAgKSsNCiAgICMgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKCI4NzM5ODUwMCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTgwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5MDAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODk1MCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA1NTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDY5MDAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwOTkwMCIpLA0KICAgIyAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIlBNMSIsICJQTTIiLCAiUE0zIiwgIlBNNCIsICJQTTUiLCAiUE02IiwgIlBNNyIpDQogICAjICkrDQogICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLA0KICAgICAgICAgICAgICAgc2U9RkFMU0UsICNzZSBkZWl4YXIgVFJVRSBnZXJhIG8gaW50ZXJ2YWxvIGRlIGNvbmZpYW7Dp2EgZGUgOTUlDQogICAgICAgICAgICAgICBhZXMoZ3JvdXA9MSksDQogICAgICAgICAgICAgICBhbHBoYT0uNSwNCiAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRSwNCiAgICAgICAgICAgICAgIHNpemUgPSAxKSsNCiAgIHRoZW1lX2dyYWZzKCkNCikNCmBgYA0KDQojIyMgU8OzbGlkb3MgVG90YWlzIHsjc2VjLXPDs2xpZG9zLXRvdGFpc30NCg0KTyBwYXLDom1ldHJvIGBTw7NsaWRvcyBUb3RhaXNgIG7Do28gdGV2ZSBtZWRpw6fDtWVzIG5vIHBlcsOtb2RvIGFuYWxpc2FkbywgZW50w6NvIGZpY2EgYXJtYXplbmFkbyBuYSB0YWJlbGEgY29tbyB2YWxvciB2YXppbywgb3UgYHJgTkFcYC4NCg0KYGBge3IgR3LDoWZpY28gU8OzbFRvdCwgZmlnLmNhcD0ic8OzbGlkb3MtdG90YWlzIiwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGZvbGQucGxvdD1GQUxTRSwgZXJyb3IgPSBUUlVFfQ0KIyAoZ3JhZl9zb2xpZG9zX3RvdGFpcyA8LSBnZ3Bsb3QocGxhbl9saXRvcmFsX21lZGlvLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKGNvZF9lc3RhY2FvLA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvbGlkb3NfdG90YWlzKSkrDQojICAgIGFubm90YXRlKCJyZWN0IiwNCiMgICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQojICAgICAgICAgICAgIHltaW4gPSA1MDAsIHltYXggPSBJbmYsDQojICAgICAgICAgICAgIGFscGhhID0gMSwNCiMgICAgICAgICAgICAgZmlsbD0iI2FjNTA3OSIpKyAjPnBpb3IgY2xhc3NlDQojICAgIGFubm90YXRlKCJyZWN0IiwNCiMgICAgICAgICAgICAgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsDQojICAgICAgICAgICAgIHltaW4gPSAtSW5mLCB5bWF4ID0gNTAwLA0KIyAgICAgICAgICAgICBhbHBoYSA9IDEsDQojICAgICAgICAgICAgIGZpbGw9IiM4ZGNkZWIiKSsgI2NsYXNzZSAxDQojICAgIHN0YXRfYm94cGxvdChnZW9tID0gJ2Vycm9yYmFyJywNCiMgICAgICAgICAgICAgICAgIHdpZHRoPTAuMywNCiMgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSkrDQojICAgIGdlb21fYm94cGxvdChmaWxsPScjRjhGOEZGJywNCiMgICAgICAgICAgICAgICAgIGNvbG9yPSJibGFjayIsDQojICAgICAgICAgICAgICAgICBvdXRsaWVyLnNoYXBlID0gMSwgI3NlIGRlaXhhciBOQSBmaWNhIHPDsyBvIGppdHRlciwgc2UgbsOjbywgZGVpeGEgMQ0KIyAgICAgICAgICAgICAgICAgd2lkdGg9IDAuNykrDQojICAgICMgZmFjZXRfd3JhcCh+cGVyaW9kbykrDQojICAgIGxhYnModGl0bGUgPSAiU8OzbGlkb3MgdG90YWlzIiwNCiMgICAgICAgICB4PSJFc3Rhw6fDo28iLA0KIyAgICAgICAgIHk9IiIpKw0KIyAgICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAuMDEsIDAuMDUpKSwNCiMgICAgICAgICAgICAgICAgICAgICAgIG4uYnJlYWtzID0gOCwNCiMgICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMCwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KHBsYW5fbGl0b3JhbF9tZWRpbyRzb2xpZG9zX3RvdGFpcywgbmEucm0gPSBUUlVFKQ0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLA0KIyAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2NhbGVzOjpudW1iZXJfZm9ybWF0KGFjY3VyYWN5ID0gMSwNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNpbWFsLm1hcmsgPSAiLCIsDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlnLm1hcmsgPSAiICIpKSsNCiMgICAgZ2diZWVzd2FybTo6Z2VvbV9xdWFzaXJhbmRvbSgNCiMgICAgICBzaXplID0gMS4yLA0KIyAgICAgIGFscGhhID0gLjI1LA0KIyAgICAgIHdpZHRoID0gLjA3LA0KIyAgICApKw0KIyAgICAjIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gYygiODczOTg1MDAiLCANCiMgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTgwIiwgDQojICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODkwMCIsIA0KIyAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5NTAiLCANCiMgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA1NTAwIiwgDQojICAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwNjkwMCIsIA0KIyAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDk5MDAiKSwNCiMgICAgIyAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIlBNMSIsICJQTTIiLCAiUE0zIiwgIlBNNCIsICJQTTUiLCAiUE02IiwgIlBNNyIpDQojICAgICMgKSsNCiMgICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwNCiMgICAgICAgICAgICAgICAgc2U9RkFMU0UsICNzZSBkZWl4YXIgVFJVRSBnZXJhIG8gaW50ZXJ2YWxvIGRlIGNvbmZpYW7Dp2EgZGUgOTUlDQojICAgICAgICAgICAgICAgIGFlcyhncm91cD0xKSwNCiMgICAgICAgICAgICAgICAgYWxwaGE9LjUsDQojICAgICAgICAgICAgICAgIG5hLnJtID0gVFJVRSwNCiMgICAgICAgICAgICAgICAgc2l6ZSA9IDEpKw0KIyAgICB0aGVtZV9ncmFmcygpDQojICkNCmBgYA0KDQojIyMgQ29uZHV0aXZpZGFkZSB7I3NlYy1jb25kdXRpdmlkYWRlfQ0KDQpgYGB7ciBHcsOhZmljbyBjb25kX2VsZXQsIGZpZy5jYXA9ImNvbmR1dGl2aWRhZGUtZWxldHJpY2EiLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgZm9sZC5wbG90PUZBTFNFfQ0KKGdyYWZfY29uZF9lbGV0IDwtIGdncGxvdChwbGFuX2xpdG9yYWxfbWVkaW8sDQogICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyhjb2RfZXN0YWNhbywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbmR1dGl2aWRhZGUpKSsNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDUwMCwgeW1heCA9IEluZiwNCiAgICAgICAgICAgIGFscGhhID0gMSwNCiAgICAgICAgICAgIGZpbGwgPSAiI2ViNTY2MSIpKyAjY2xhc3NlIDQNCiAgIGFubm90YXRlKCJyZWN0IiwNCiAgICAgICAgICAgIHhtaW4gPSAtSW5mLCB4bWF4ID0gSW5mLA0KICAgICAgICAgICAgeW1pbiA9IDAsIHltYXggPSA1MDAsDQogICAgICAgICAgICBhbHBoYSA9IDEsDQogICAgICAgICAgICBmaWxsID0gIiM4ZGNkZWIiKSsgI2NsYXNzZSAxDQogICBzdGF0X2JveHBsb3QoZ2VvbSA9ICdlcnJvcmJhcicsDQogICAgICAgICAgICAgICAgd2lkdGg9MC4zLA0KICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjY1KSkrDQogICBnZW9tX2JveHBsb3QoZmlsbD0nI0Y4RjhGRicsDQogICAgICAgICAgICAgICAgY29sb3I9ImJsYWNrIiwNCiAgICAgICAgICAgICAgICBvdXRsaWVyLnNoYXBlID0gMSwgI3NlIGRlaXhhciBOQSBmaWNhIHPDsyBvIGppdHRlciwgc2UgbsOjbywgZGVpeGEgMQ0KICAgICAgICAgICAgICAgIHdpZHRoPSAwLjcpKw0KICAgIyBmYWNldF93cmFwKH5wZXJpb2RvKSsNCiAgIGxhYnModGl0bGUgPSAiQ29uZHV0aXZpZGFkZSBlbMOpdHJpY2EiLA0KICAgICAgICB4PSJFc3Rhw6fDo28iLA0KICAgICAgICB5PSLCtW1ob3MvY20iKSsNCiAgIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMC4wNSwgMC4wNSkpLA0KICAgICAgICAgICAgICAgICAgICAgIG4uYnJlYWtzID0gOCwNCiAgICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKG1pbihwbGFuX2xpdG9yYWxfbWVkaW8kY29uZHV0aXZpZGFkZSwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChwbGFuX2xpdG9yYWxfbWVkaW8kY29uZHV0aXZpZGFkZSwgbmEucm0gPSBUUlVFKSksDQogICAgICAgICAgICAgICAgICAgICAgdHJhbnMgPSAibG9nMTAiLA0KICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNjYWxlczo6bnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY2ltYWwubWFyayA9ICIsIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmlnLm1hcmsgPSAiICIpKSsNCiAgIGdnYmVlc3dhcm06Omdlb21fcXVhc2lyYW5kb20oDQogICAgIHNpemUgPSAxLjIsDQogICAgIGFscGhhID0gLjI1LA0KICAgICB3aWR0aCA9IC4wNywNCiAgICkrDQogICAjIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gYygiODczOTg1MDAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzM5ODk4MCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3Mzk4OTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODczOTg5NTAiLCANCiAgICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI4NzQwNTUwMCIsIA0KICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjg3NDA2OTAwIiwgDQogICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiODc0MDk5MDAiKSwNCiAgICMgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJQTTEiLCAiUE0yIiwgIlBNMyIsICJQTTQiLCAiUE01IiwgIlBNNiIsICJQTTciKQ0KICAgIyApKw0KICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwNCiAgICAgICAgICAgICAgIHNlPUZBTFNFLCAjc2UgZGVpeGFyIFRSVUUgZ2VyYSBvIGludGVydmFsbyBkZSBjb25maWFuw6dhIGRlIDk1JQ0KICAgICAgICAgICAgICAgYWVzKGdyb3VwPTEpLA0KICAgICAgICAgICAgICAgYWxwaGE9LjUsDQogICAgICAgICAgICAgICBuYS5ybSA9IFRSVUUsDQogICAgICAgICAgICAgICBzaXplID0gMSkrDQogICB0aGVtZV9ncmFmcygpKw0KICAgdGhlbWUoDQogICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KA0KICAgICAgIGFuZ2xlID0gOTAsDQogICAgICAgIyBzaXplPTE1LA0KICAgICAgICMgZmFjZT0yDQogICAgICkNCiAgICkNCikNCmBgYA0KDQojIyBBbsOhbGlzZSBhbyBsb25nbyBkbyB0ZW1wbyB7I3NlYy1hbsOhbGlzZS1hby1sb25nby1kby10ZW1wb30NCg0KUGFyYSBnZXJhciB1bSBncsOhZmljbyBhbyBsb25nbyBkbyB0ZW1wbyBwcmEgY2FkYSB1bWEgZGFzIGVzdGHDp8O1ZXMgw6kgbmVjZXNzw6FyaW8gYWx0ZXJhciBvIGBhbm9faW5pY2lhbGAgZSBvIGBhbm9fZmluYWxgLiBUYW1iw6ltIMOpIG5lY2Vzc8OhcmlvIHNlbGVjaW9uYXIgcXVhbCBwYXLDom1ldHJvIHF1ZSBzZSBxdWVyIGZhemVyIGEgdmlzdWFsaXphw6fDo28uDQoNCmBgYHtyIGdyw6FmaWNvIGFvIGxvbmdvIGRvIHRlbXBvLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgZm9sZC5wbG90PUZBTFNFfQ0KYW5vX2luaWNpYWwgPC0gMjAxNQ0KYW5vX2ZpbmFsIDwtIDIwMjINCg0KKHRpbWVsaW5lIDwtIHBsYW5fbGl0b3JhbF9tZWRpbyAlPiUNCiAgZmlsdGVyKGFub19jb2xldGEgPiBhbm9faW5pY2lhbCAmDQogICAgICAgICAgIGFub19jb2xldGEgPD0gYW5vX2ZpbmFsKSAlPiUNCiAgZHBseXI6OnNlbGVjdChjb2RfZXN0YWNhbywgZV9jb2xpLCBkYXRhX2NvbGV0YSkgJT4lDQogIGdyb3VwX2J5KGNvZF9lc3RhY2FvKSAlPiUNCiAgZ2dwbG90KA0KICAgIGFlcyh4ID0gZGF0YV9jb2xldGEsDQogICAgICAgIHkgPSBlX2NvbGksDQogICAgICAgIGNvbG9yID0gY29kX2VzdGFjYW8NCiAgICApKSsNCiAgICBnZW9tX2xpbmUoDQogICAgICAjIGFlcyhjb2xvciA9IENPRElHTyksDQogICAgICBuYS5ybSA9IFRSVUUpKw0KICAgIGdlb21fcG9pbnQoDQogICAgICAjIGFlcyhjb2xvciA9IENPRElHTyksDQogICAgICBuYS5ybSA9IFRSVUUpKw0KICAgIHNjYWxlX3hfZGF0ZSgNCiAgICAgIGxpbWl0cyA9IGFzLkRhdGUoYygNCiAgICAgICAgeW1kKGdsdWUoInthbm9faW5pY2lhbH0tMDEtMDEiKSksDQogICAgICAgIHltZChnbHVlKCJ7YW5vX2ZpbmFsfS0wMS0wMSIpKQ0KICAgICAgICAjIE5BICNwb2RlIHVzYXIgTkEgdGFtYsOpbQ0KICAgICAgKSksDQogICAgICBleHBhbmQgPSBjKDAuMCwgMC4wKSwNCiAgICAgIGRhdGVfYnJlYWtzID0gIjIgeWVhcnMiLA0KICAgICAgbWlub3JfYnJlYWtzID0gIjEgeWVhcnMiLA0KICAgICAgZGF0ZV9sYWJlbHMgPSAiJVkiLA0KICAgICkrDQogICMgZ2VvbV9zbW9vdGgoDQogICMgICBtZXRob2QgPSAibG0iLCAjcmVncmVzc2FvIGxpbmVhcg0KICAjICAgc2UgPSBUUlVFLCAjc2UgZGVpeGFyIFRSVUUgZ2VyYSBvIGludGVydmFsbyBkZSBjb25maWFuw6dhIGRlIDk1JQ0KICAjICAgYWVzKGdyb3VwID0gMSksDQogICMgICBhbHBoYSA9LjUsDQogICMgICBuYS5ybSA9IFRSVUUsDQogICMgICBzaXplID0gMC4zLA0KICAjICAgIyBmdWxscmFuZ2UgPSBUUlVFLA0KICAjICAgc2hvdy5sZWdlbmQgPSBUUlVFDQogICMgKSsNCiAgc3RhdF9zbW9vdGgoDQogICAgZ2VvbSA9ICJzbW9vdGgiLA0KICAgICMgc3BhbiA9IDAuMiwNCiAgICBzZSA9IFRSVUUsICNzZSBkZWl4YXIgVFJVRSBnZXJhIG8gaW50ZXJ2YWxvIGRlIGNvbmZpYW7Dp2EgZGUgOTUlDQogICAgIyBhZXMoZ3JvdXAgPSAxKSwNCiAgICAjIGFscGhhID0uNSwNCiAgICBuYS5ybSA9IFRSVUUsDQogICAgIyBzaXplID0gMC4zLA0KICAgIGZ1bGxyYW5nZSA9IFRSVUUsDQogICAgc2hvdy5sZWdlbmQgPSBUUlVFDQogICkrDQogIGZhY2V0X3dyYXAoDQogICAgfmNvZF9lc3RhY2FvLA0KICAgIG5yb3cgPSA0LA0KICApKw0KICB0aGVtZV9idygpDQopDQpgYGANCg0KIyMgQ29ycmVsYcOnw6NvIHsjc2VjLWNvcnJlbGHDp8Ojb30NCg0KYGBge3IgQ29ycmVsYcOnw6NvLCBmaWcuY2FwPSJjb3JyZWxhw6fDo28tcGFyYW1ldHJvcy1xdWFsaWRhZGUtYWd1YSIsIHRpbWVfaXQgPSBUUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGZvbGQucGxvdD1GQUxTRX0NCnBhcmFtZXRyb3NfaXFhX2xpdF9tZWRpbyA8LSBwbGFuX2xpdG9yYWxfbWVkaW8gJT4lDQogIGRwbHlyOjpzZWxlY3QoY29kX2VzdGFjYW8sDQogICAgICAgICBwaCwNCiAgICAgICAgIGRibywNCiAgICAgICAgIGVfY29saSwNCiAgICAgICAgIG5pdHJvZ2VuaW9fYW1vbmlhY2FsLA0KICAgICAgICAgIyBuaXRyb19ramVsZGFobCwNCiAgICAgICAgICMgbml0cm9fdG90YWwsDQogICAgICAgICBmb3Nmb3JvX3RvdGFsLA0KICAgICAgICAgdGVtcGVyYXR1cmFfZGFfYWd1YSwNCiAgICAgICAgIHR1cmJpZGV6LA0KICAgICAgICAgc29saWRvc190b3RhaXMsDQogICAgICAgICBveGlnZW5pb19kaXNzb2x2aWRvLA0KICAgICAgICAgY29uZHV0aXZpZGFkZSwNCiAgICAgICAgIGFub19jb2xldGENCiAgICAgICAgICkgDQoNCnBhcmFtZXRyb3NfaXFhX2xpdF9tZWRpbyAlPiUgDQogIGRwbHlyOjpzZWxlY3QoDQogICAgLWNvZF9lc3RhY2FvLA0KICAgIC1hbm9fY29sZXRhLA0KICAgIC1zb2xpZG9zX3RvdGFpcw0KICAgICkgJT4lDQogICMgZ3JvdXBfYnkoY29kX2VzdGFjYW8pICU+JQ0KICByZW5hbWUoDQogICAgQ0UgPSBjb25kdXRpdmlkYWRlLA0KICAgIE9EID0gb3hpZ2VuaW9fZGlzc29sdmlkbywNCiAgICAjIFNUID0gc29saWRvc190b3RhaXMsDQogICAgVHVyYiA9IHR1cmJpZGV6LA0KICAgIFRlbXAgPSB0ZW1wZXJhdHVyYV9kYV9hZ3VhLA0KICAgIFB0b3QgPSBmb3Nmb3JvX3RvdGFsLA0KICAgIE5BbW9uID0gbml0cm9nZW5pb19hbW9uaWFjYWwsDQogICAgcEggPSBwaCwNCiAgICBEQk8gPSBkYm8sDQogICAgRV9jb2xpID0gZV9jb2xpDQogICAgIyBOVEsgPSBuaXRyb19ramVsZGFobA0KICApICU+JSANCiAgZ2djb3JyKA0KICAgIG1ldGhvZCA9DQogICAgImNvbXBsZXRlLm9icyIsDQogICAgIyAicGVhcnNvbiIsDQogICAgIyAicGFpcndpc2UiLA0KICAgIG5hbWUgPSAiQ29ycmVsYcOnw6NvIiwNCiAgICBsYWJlbCA9IFRSVUUsDQogICAgbGFiZWxfYWxwaGEgPSBUUlVFLA0KICAgIGRpZ2l0cyA9IDMsDQogICAgbG93ID0gIiMzQjlBQjIiLA0KICAgIG1pZCA9ICIjRUVFRUVFIiwNCiAgICBoaWdoID0gIiNGMjFBMDAiLA0KICAgICMgcGFsZXR0ZSA9ICJSZFlsQnUiLA0KICAgIGxheW91dC5leHAgPSAwLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJsZWZ0IiwNCiAgICBsYWJlbF9yb3VuZCA9IDMsDQogICAgIyBsZWdlbmQuc2l6ZSA9IDE4LA0KICAgIGdlb20gPSAidGlsZSIsDQogICAgbmJyZWFrcyA9IDEwLA0KICApKw0KICBsYWJzKHRpdGxlID0gIkNvcnJlbGHDp8OjbyBlbnRyZSBwYXLDom1ldHJvcyBmw61zaWNvLXF1w61taWNvcyBuYVxuQmFjaWEgSGlkcm9ncsOhZmljYSBkbyBMaXRvcmFsIE3DqWRpbyIpKw0KICB0aGVtZV9saW5lZHJhdygpKw0KICB0aGVtZSgNCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuMTUsIDAuNiksDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAjIGxlZ2VuZC5zcGFjaW5nID0gdW5pdChlbGVtZW50X3RleHQoKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIyB1bml0cyA9IDUpDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxNikNCiAgKQ0KYGBgDQoNCiMjIyBDb3JyZWxhw6fDo28gZW50cmUgcGFyw6JtZXRyb3MgcXVlIGNvbXDDtWVtIG8gSVFBIGNvbSBzaWduaWZpY8OibmNpYSBlc3RhdMOtc3RpY2ENCg0KYGBge3IgZ3JhZi1jb3JyZWwtZXN0YXRpc3RpY2EsIHRpbWVfaXQgPSBUUlVFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlID0gRkFMU0V9DQojIEdyw6FmaWNvIGRhcyBjb3JyZWxhw6fDtWVzIGVudHJlIHRvZG9zIG9zIHBhcsOibWV0cm9zIGNvbSBzaWduaWZpY8OibmNpYQ0KY29ycmVsX0lRQV9saXRfbWVkaW8gPC0gcGFyYW1ldHJvc19pcWFfbGl0X21lZGlvICU+JQ0KICBkcGx5cjo6c2VsZWN0KC1jb2RfZXN0YWNhbykgJT4lDQogIGdncGFpcnModGl0bGUgPSAiQ29ycmVsYcOnw6NvIGVudHJlIHBhcsOibWV0cm9zIHF1ZSBjb21ww7VlbSBvIElRQSIsDQogICAgICAgICAgYXhpc0xhYmVscyA9ICJzaG93IikNCiMgY29ycmVsX0lRQV9saXRfbWVkaW8NCmBgYA0KDQojIyBTYWx2YXIgb3MgZ3LDoWZpY29zIHsjc2VjLXNhbHZhci1vcy1ncsOhZmljb3N9DQoNClJlcGxpY2FyIGVzc2UgbW9kZWxvIHByb3MgZ3LDoWZpY29zIHF1ZSBkZXNlamEgc2FsdmFyLlwNCjEuIENyaWFyIG5vdm8gY29kZSBjaHVuayAoYEN0cmwrQWx0K0lgKVwNCjIuIENvcGlhciBhIGbDs3JtdWxhIGFiYWl4b1wNCjMuIENvbGFyIG5lc3NlIG5vdm8gY29kZSBjaHVua1wNCjQuDQoNCk9zIGdyw6FmaWNvcyBmaWNhcsOjbyBzYWx2b3MgZW0gdW1hIHBhc3RhIHF1ZSBpcsOhIHNlciBjcmlhZGEgYSBwYXJ0aXIgZG8gY8OzZGlnby4NCg0KYGBge3Igc2FsdmFyLWdyYWZpY29zLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCmdnc2F2ZSgiZ3JhZl9vZC5wbmciLA0KICAgICAgIHBsb3QgPSBncmFmX29kLCAjYWx0ZXJhY2FvDQogICAgICAgcGF0aCA9ICIuL2dyYWZpY29zIiwNCiAgICAgICBkcGkgPSAzMDAsDQogICAgICAgdHlwZSA9ICJjYWlybyIpDQpgYGANCg0KIyBNYXBhcyB7I3NlYy1tYXBhc30NCg0KIyMgUGFjb3RlcyBwcmEgZ2VyYcOnw6NvIGRlIG1hcGFzIHsjc2VjLXBhY290ZXMtcHJhLWdlcmHDp8Ojby1kZS1tYXBhcyAucGFjb3Rlc30NCg0KYGBge3IgcGFjb3Rlcy1nZW9lc3BhY2lhaXMsIG1lc3NhZ2UgPSBUUlVFLCB3YXJuaW5nID0gRkFMU0V9DQpwYWNtYW46OnBfbG9hZChyYXN0ZXIsIGxlYWZsZXQsIHNmDQogICAgICAgICAgICAgICAjIHByZXR0eW1hcHIsIHJqc29uLCByb3NtLA0KICAgICAgICAgICAgICAgIyBnZ3NwYXRpYWwNCiAgICAgICAgICAgICAgICMgcmdkYWwsIHJnZW9zLA0KICAgICAgICAgICAgICAgIyBndG9vbHMsIHRpZHl2ZXJzZSwgcm5hdHVyYWxlYXJ0aCwNCiAgICAgICAgICAgICAgICMgcm5hdHVyYWxlYXJ0aGRhdGEsIHJldGljdWxhdGUsIG1hcHRvb2xzLA0KICAgICAgICAgICAgICAgIyBtYXBzLCBnZ3Bsb3QyLCBnZ3NwYXRpYWwsIHJnZW9zLCBnZ21hcA0KICAgICAgICAgICAgICAgKQ0KYGBgDQoNCiMjIE1hcGEgZXN0w6F0aWNvIHsjc2VjLW1hcGEtZXN0w6F0aWNvfQ0KDQpJbXBvcnRhbmRvIGFzIGluZm9ybWHDp8O1ZXMgbmVjZXNzw6FyaWFzIHByYSBnZXJhciBtYXBhcyBkZSBwcmVjaXBpdGHDp8Ojby5cDQpGb250ZTogR0FETSBbXjFdLCBbXjJdDQoNClteMV06IDxodHRwczovL2dhZG0ub3JnL21hcHMvQlJBLmh0bWw+DQoNClteMl06IDxodHRwczovL2dhZG0ub3JnL2RhdGEuaHRtbD4NCg0KYGBge3IgbWFwYS1lc3RhdGljbywgZmlnLmNhcCA9ICJNYXBhIGVzdMOhdGljbyBkbyBSUyJ9DQpCcmFzaWwgPC0gZ2V0RGF0YSgNCiAgJ0dBRE0nLA0KICBjb3VudHJ5ID0gJ0JyYXppbCcsDQogIGxldmVsID0gMw0KKSAlPiUNCiAgc3RfYXNfc2YoKQ0KDQpSUyA8LSBzdWJzZXQoQnJhc2lsLA0KICAgICAgICAgICAgIE5BTUVfMSA9PSAiUmlvIEdyYW5kZSBkbyBTdWwiKQ0KDQpsYmwgPC0gZGF0YS5mcmFtZShtb250aF9hYmIgPSBtb250aC5hYmIsDQogICAgICAgICAgICAgICAgICBtZXMgPSAxOjEyKQ0KDQpwbGFuX2xpdG9yYWxfbWVkaW8gJT4lDQogIGdncGxvdCgNCiAgICAjIGFlcyh4ID0gbG9uZ3RpdHVkZSwNCiAgICAjICAgICB5ID0gbGF0aXR1ZGUsDQogICAgIyAgICAgbWFwX2lkID0gcmVnaW9uKQ0KICApKw0KICBnZW9tX3NmKA0KICAgIGRhdGEgPSBSUw0KICApKw0KICB0aGVtZV9idygpDQoNCiMgRGVmaW5pbmRvIG8gU1JDDQpSUyA8LSBSUyAlPiUNCiAgc3RfdHJhbnNmb3JtIChjcnMgPSA0Njc0KSAjNDMyNiA9IFdHUzg0LCA0Njc0ID0gU0lSR0FTMjAwMA0KYGBgDQoNCiMjIE1hcGEgaW50ZXJhdGl2byBjb20gbG9jYWxpemHDp8OjbyBkb3MgcG9udG9zIGRlIG1vbml0b3JhbWVudG8geyNzZWMtbWFwYS1pbnRlcmF0aXZvLWNvbS1sb2NhbGl6YcOnw6NvLWRvcy1wb250b3MtZGUtbW9uaXRvcmFtZW50b30NCg0KYGBge3IgbWFwYS1pbnRlcmF0aXZvLCBmaWcuY2FwID0gIk1hcGEgaW50ZXJhdGl2byJ9DQpsZWFmbGV0KFJTKSAlPiUgDQogIGFkZFByb3ZpZGVyVGlsZXMoDQogICAgIkVzcmkuV29ybGRJbWFnZXJ5IiAjSW1hZ2VtIGRlIHNhdMOpbGl0ZQ0KICAgICMgIk9wZW5TdHJlZXRNYXAuTWFwbmlrIiAjT3BlblN0cmVldE1hcCAtPiBTb2Z0d2FyZSBsaXZyZQ0KICApICU+JSANCiAgYWRkQ2lyY2xlTWFya2VycygNCiAgICBkYXRhID0gcGxhbl9saXRvcmFsX21lZGlvLA0KICAgIGxuZyA9IH5sb25naXR1ZGUsDQogICAgbGF0ID0gfmxhdGl0dWRlLA0KICAgIHBvcHVwID0gfnBhc3RlKA0KICAgICAgIjxiPkVzdGHDp8Ojbzo8L2I+Iix7Y29kX2VzdGFjYW99LCI8YnI+IiwNCiAgICAgICI8Yj5SZWN1cnNvIGjDrWRyaWNvOjwvYj4iLCByZWN1cnNvX2hpZHJpY28sICI8YnI+IiwNCiAgICAgICI8Yj5NdW5pY8OtcGlvOjwvYj4iLCBtdW5pY2lwaW8sDQogICAgICBzZXAgPSAiICINCiAgICApDQogICkgDQpgYGANCg0KIyMgTWFwYSBkZSBwcmVjaXBpdGHDp8OjbyBhbnVhbA0KDQpgYGB7ciBFeHRyYWluZG8gb3MgZGFkb3MgcmFzdGVyIGRlIHByZWNpcGl0YcOnw6NvLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCiMgc3RfY2VudHJvaWQoUlMpDQojIA0KIyBQcmVjIDwtIGdldERhdGEoDQojICAgIndvcmxkY2xpbSIsIA0KIyAgIHZhciA9ICJwcmVjIiwgDQojICAgcmVzID0gMC41LCANCiMgICBsYXQgPSBjKC0zMC4wMzMwNTYsIC0yOS42ODQxNyksICNwcm9jdXJhciBsYXQgbG9uZyBubyBnb29nbGUgZSBhbHRlcmFyIGFxdWkNCiMgICBsb24gPSBjKC01MS4yMzAwMDAsIC01My44MDY5NCkNCiMgKQ0KIyANCiMgUHJlY19SUyA8LSBQcmVjICU+JSANCiMgICBjcm9wKFJTKSAlPiUgDQojICAgbWFzayhSUywgbmEucm0gPSBUUlVFKQ0KIyANCiMgcGxvdChQcmVjX1JTKQ0KIyANCiMgUFBBbnVhbF9SUyA8LSBkby5jYWxsKCJzdW0iLCANCiMgICAgICAgICAgICAgICAgICAgICAgICB1bnN0YWNrKFByZWNfUlMpKQ0KIyBwbG90KFBQQW51YWxfUlMpDQpgYGANCg0KYGBge3IgRWxhYm9yYW5kbyBvcyBtZXNlcyBkZSBwcmVjaXBpdGHDp8OjbywgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9DQojIHZscyA8LSByYXN0ZXJUb1BvaW50cyhQcmVjX1JTKSAlPiUgDQojICAgYXNfdGliYmxlKCkgJT4lIA0KIyAgIGdhdGhlcih2YXIsIHZhbHVlLCAteCwgLXkpICU+JSANCiMgICBtdXRhdGUobWVzID0gcGFyc2VfbnVtYmVyKHZhcikpICU+JSANCiMgICBpbm5lcl9qb2luKC4sIGxibCwgYnkgPSAnbWVzJykgJT4lIA0KIyAgIGRwbHlyOjpzZWxlY3QoeCwgeSwgbW9udGhfYWJiLCB2YWx1ZSkgJT4lIA0KIyAgIG11dGF0ZShtb250aF9hYmIgPSBmYWN0b3IobW9udGhfYWJiLCBsZXZlbHMgPSBtb250aC5hYmIpKQ0KIyANCiMgdmxzICU+JSANCiMgICBmaWx0ZXIobW9udGhfYWJiID09ICdKYW4nKQ0KIyANCiMgc3VtbWFyeSh2bHMkdmFsdWUpICNkZXNjb2JyZSBvIHZhbG9yIG3DrW5pbW8sIG3DqWRpbyBlIG3DoXhpbW8gZGUgcHJlY2lwaXRhw6fDo28NCmBgYA0KDQojIyBNYXBhIGNvbSBwcmVjaXBpdGHDp8OjbyBtZW5zYWwNCg0KQ2FzbyBxdWVpcmEgZ2VyYXIgdW0gbWFwYSBjb20gYSBwcmVjaXBpdGHDp8OjbyBtZW5zYWwsIGFsdGVybmFyIG8gaW5jbHVkZSBwYXJhIGBUUlVFYC4gQSBnZXJhw6fDo28gZGVzc2UgbWFwYSBkZW1hbmRhIGJhc3RhbnRlIHByb2Nlc3NhbWVudG8sIHJlY29tZW5kw6F2ZWwgbWFudGVyIGBpbmNsdWRlID0gRkFMU0VgIGUgYGVjaG8gPSBGQUxTRWAuDQoNCmBgYHtyIG1hcGFzLXByZWNpcGl0YWNhby1tZW5zYWwsIGluY2x1ZGUgPSBUUlVFLCBlY2hvID0gRkFMU0V9DQojIGNvcmVzMTwtIGMoJyNmZjQyMjMnLCcjZjE5ZTIxJywnI2ZmZWUyMScsJyMwMGZmZmYnLCAnIzEwYWViZScsICcjMTY1ZGZmJywnIzkzMzFkYycpDQojIGNvcmVzMjwtIGMoJyM5MzMxZGMnLCAnIzE2NWRmZicsICcjMTBhZWJlJywgJyMwMGZmZmYnLCAnI2ZmZWUyMScsICcjZjE5ZTIxJywgJyNmZjQyMjMnKQ0KIyANCiMgDQojIChnZyA8LSBnZ3Bsb3QodmxzKSAgKw0KIyAgICAgZ2VvbV90aWxlKGFlcyh4ID0geCwgDQojICAgICAgICAgICAgICAgICAgIHkgPSB5LCANCiMgICAgICAgICAgICAgICAgICAgZmlsbCA9IHZhbHVlKSkgKw0KIyAgICAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3VycyA9IGNvcmVzMSwgDQojICAgICAgICAgICAgICAgICAgICAgICAgICBuYS52YWx1ZSA9ICd3aGl0ZScsIA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLCAyNTApLCANCiMgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLCAyNTAsIDI1KSkgKw0KIyAgICAgZ2VvbV9zZihkYXRhID0gUlMsIA0KIyAgICAgICAgICAgICBmaWxsID0gTkEsIA0KIyAgICAgICAgICAgICBjb2xvciA9ICdibGFjaycsIA0KIyAgICAgICAgICAgICBzaXplID0gMC4yKSsNCiMgICAgIGZhY2V0X3dyYXAofiBtb250aF9hYmIpICsNCiMgICAgICMgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoLTcyLjUsIC03MS4wLCAtNjkuNSkpICsNCiMgICAgIGdndGl0bGUoIlByZWNpcGl0YcOnw6NvIG1lbnNhbCAtIFJTIikrDQojICAgICBsYWJzKHRpdGxlID0gJ1ByZWNpcGl0YcOnw6NvIE1lbnNhbCAtIFJTJywNCiMgICAgICAgICAgZmlsbCA9ICdtbScsICANCiMgICAgICAgICAgeCA9ICdMb25naXR1ZGUnLCANCiMgICAgICAgICAgeSA9ICdMYXRpdHVkZScsIA0KIyAgICAgICAgICBjYXB0aW9uID0gIkxlb25hcmRvIEZlcm5hbmRlcyBXaW5rIikgKw0KIyAgICAgbGFicygNCiMgICAgICAgY2FwdGlvbiA9ICJGb250ZTogaHR0cHM6Ly9vc21kYXRhLm9wZW5zdHJlZXRtYXAuZGUvIg0KIyAgICAgKSsNCiMgICAgIHRoZW1lX2J3KCkgKw0KIyAgICAgdGhlbWUoDQojICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiksDQojICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksDQojICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQojICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChzaXplID0gMiwgDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj0id2hpdGUiKSwNCiMgICAgICAgbGVnZW5kLmtleS53aWR0aCA9IHVuaXQoNSwgJ2xpbmUnKSwNCiMgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScsDQojICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoDQojICAgICAgICAgc2l6ZSA9IDE2LCANCiMgICAgICAgICBoanVzdCA9IDAuNSwgDQojICAgICAgICAgY29sb3IgPSAiYmxhY2siLCANCiMgICAgICAgICBmYWNlID0gImJvbGQiDQojICAgICAgICksDQojICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KA0KIyAgICAgICAgIGZhY2UgPSAiYm9sZCIsIA0KIyAgICAgICAgIGNvbG9yID0gImJsYWNrIiwgDQojICAgICAgICAgc2l6ZSA9IDgNCiMgICAgICAgKSwNCiMgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoDQojICAgICAgICAgYW5nbGUgPSA5MCwNCiMgICAgICAgICBmYWNlID0gImJvbGQiLCANCiMgICAgICAgICBjb2xvciA9ICJibGFjayIsIA0KIyAgICAgICAgIHNpemUgPSA4DQojICAgICAgICksDQojICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoDQojICAgICAgICAgZmFjZT0gJ2JvbGQnLCANCiMgICAgICAgICBzaXplPSAxNCwgDQojICAgICAgICAgaGp1c3Q9IDAuNSwgDQojICAgICAgICAgY29sb3I9ICdibGFjaycNCiMgICAgICAgKSwNCiMgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSd3aGl0ZScpLA0KIyAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KA0KIyAgICAgICAgIHNpemUgPSAxMSwgDQojICAgICAgICAgaGp1c3QgPSAwLjgsIA0KIyAgICAgICAgIGZhY2UgPSAiaXRhbGljIiwgDQojICAgICAgICAgY29sb3IgPSAicmVkIiwgIyIjNGU0ZDQ3Ig0KIyAgICAgICAgIGZhbWlseT0ic2VyaWYiDQojICAgICAgICksDQojICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dCgNCiMgICAgICAgICBzaXplID0gMTAsIA0KIyAgICAgICAgIGhqdXN0ID0gMC45NSwgDQojICAgICAgICAgY29sb3IgPSAiYmxhY2siLA0KIyAgICAgICApDQojICAgICApICsNCiMgICAgIGd1aWRlcyhzaGFwZSA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSAxMCkpKQ0KIyApDQoNCnBhY21hbjo6cF9sb2FkKA0KICBEaWFncmFtbWVSDQopDQpgYGANCg0KIyBSZWZlcsOqbmNpYXMgLSBMaW5rcyDDunRlaXMgeyNzZWMtbGlua3Mtw7p0ZWlzfQ0KDQpSZWNvbWVuZG8sIGFiYWl4bywgYWxndW1hcyByZWZlcsOqbmNpYXMuIFRhbWLDqW0gZGVpeG8gdW1hIHRyaWxoYSBkZSBhcHJlbmRpemFkbyBxdWUganVsZ28gc2VyIG1haXMgZsOhY2lsIGRvIHF1ZSBhIHF1ZSBwZXJjb3JyaSwgY29uZm9ybWUgZGlhZ3JhbWEgYWJhaXhvLg0KDQpgYGB7cn0NCkRpYWdyYW1tZVI6OmdyVml6KCJkaWdyYXBoIHsNCiAgZ3JhcGggWw0KICBsYXlvdXQgPSBkb3QsIA0KICByYW5rZGlyID0gTFINCiAgXQ0KICANCiAgbm9kZSBbc2hhcGUgPSBvdmFsXSAjcmVjdGFuZ2xlDQogIHJlYzEgW2xhYmVsID0gJ1RlbnRhciByZXByb2R1emlyIGPDs2RpZ29zXG5kZSBvdXRyYXMgcGVzc29hcyddDQogIHJlYzIgW2xhYmVsID0gJ0VudGVuZGVyIGEgZ3JhbcOhdGljYVxuZG9zIGdyw6FmaWNvcyddDQogIHJlYzMgW2xhYmVsID0gICdTdGVwIDMuID8/PyddDQogIHJlYzQgW2xhYmVsID0gJ1N0ZXAgNC4gUFJPRklUJ10NCiAgDQogICMgZWRnZSBkZWZpbml0aW9ucyB3aXRoIHRoZSBub2RlIElEcw0KICByZWMxIC0+IHJlYzIgLT4gcmVjMyAtPiByZWM0DQogIH0iLA0KICBoZWlnaHQgPSA1MCkNCmBgYA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCiMgYV9ncmFwaCA8LQ0KIyAgICBjcmVhdGVfZ3JhcGgoKSAlPiUgDQojICAgIGFkZF9ub2RlKCkgJT4lIA0KIyAgICBhZGRfbm9kZSgpICU+JSANCiMgICAgYWRkX2VkZ2UoDQojICAgICAgZnJvbSA9IDEsDQojICAgICAgdG8gPSAyDQojICAgICkgJT4lIA0KIyAgIGFkZF9ub2Rlc19mcm9tX3RhYmxlKA0KIyAgICAgdGFibGUgPSBub2RlX2xpc3RfMSwNCiMgICAgIGxhYmVsX2NvbCA9IGxhYmVsDQojICAgKSAlPiUgDQojICAgcmVuZGVyX2dyYXBoKGxheW91dCA9ICJuaWNlbHkiKQ0KIyANCiMgZ2V0X25vZGVfZGYoYV9ncmFwaCkNCmBgYA0KDQpgYGB7bWVybWFpZCwgZWNobz1GQUxTRX0NCiAgZ3JhcGggVEQ7DQogICAgICBBLS0+Qg0KYGBgDQoNCg0KIyMgUg0KDQpbUiBmb3IgRGF0YSBTY2llbmNlXShodHRwczovL3I0ZHMuaGFkLmNvLm56L2ludHJvZHVjdGlvbi5odG1sKQ0KDQo+IFVtIGRvcyBwcmluY2lwYWlzIGxpdnJvcyBwYXJhIHF1ZW0gZXN0w6EgcXVlcmVuZG8gYXByZW5kZXIgUi4gRXNzYSDDqSBhIDHCqiB2ZXJzw6NvLCBwdWJsaWNhZGEgZW0gMjAxNy4gRW0gMjAyMyBzZXLDoSBwdWJsaWNhZGEgYSAywqosIGF0cmF2w6lzIGRvIFtsaW5rXShodHRwczovL3I0ZHMuaGFkbGV5Lm56KS4NCg0KIyMgQ2hlYXRzaGVldHMgeyNzZWMtY2hlYXRzaGVldHN9DQoNCltDaGVhdHNoZWV0c10oaHR0cHM6Ly9wb3NpdC5jby9yZXNvdXJjZXMvY2hlYXRzaGVldHMvKQ0KDQpbR2l0SHViIGNvbSBhcyB2ZXJzw7VlcyBtYWlzIGF0dWFsaXphZGFzXShodHRwczovL2dpdGh1Yi5jb20vcnN0dWRpby9jaGVhdHNoZWV0cy8pDQoNCltnZ3Bsb3QyIGNoZWF0c2hlZXRdKGh0dHBzOi8vcG9zaXQuY28vd3AtY29udGVudC91cGxvYWRzLzIwMjIvMTAvZGF0YS12aXN1YWxpemF0aW9uLTEucGRmKQ0KDQpbZ2dwbG90MiBjaGVhdHNoZWV0IGVtIHBvcnR1Z3XDqnNdKGh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9yc3R1ZGlvL2NoZWF0c2hlZXRzL21haW4vdHJhbnNsYXRpb25zL3BvcnR1Z3Vlc2UvZGF0YS12aXN1YWxpemF0aW9uX3B0LnBkZikNCg0KW21hbmlwdWxhw6fDo28gZGUgZGFkb3MgZW0gcG9ydHVndcOqc10oaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3JzdHVkaW8vY2hlYXRzaGVldHMvbWFpbi90cmFuc2xhdGlvbnMvcG9ydHVndWVzZS9kYXRhLXdyYW5nbGluZ19wdC5wZGYpDQoNCltkcGx5ciBjaGVhdHNoZWV0XShodHRwczovL3Bvc2l0LmNvL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDIyLzEwL2RhdGEtdHJhbnNmb3JtYXRpb24tMS5wZGYpDQoNCiMjIFJtYXJrZG93biB7I3NlYy1ybWFya2Rvd259DQoNCltUdXRvcmlhbCBzb2JyZSBSTWFya2Rvd25dKGh0dHBzOi8veW91dHUuYmUvMThBVVpPV0FhemcpDQoNCltSbWFya2Rvd24gYmFzaWNzXShodHRwczovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbS9hdXRob3JpbmdfYmFzaWNzLmh0bWwpDQoNCltSTWFya2Rvd246IFRoZSBkZWZpbml0aXZlIGd1aWRlXShodHRwczovL2Jvb2tkb3duLm9yZy95aWh1aS9ybWFya2Rvd24vKQ0KDQojIyBQYWNvdGVzDQoNCltrbml0cl0oaHR0cHM6Ly95aWh1aS5vcmcva25pdHIvb3B0aW9ucy8pey5wYWNvdGVzfQ0KDQpbaW50cm8ycl0oaHR0cHM6Ly9pbnRybzJyLmNvbS9ncmFwaGljc19yLmh0bWwpDQoNCi0gICBHZXR0aW5nIHN0YXJ0ZWQgd2l0aCBSIGFuZCBSU3R1ZGlvDQoNCi0gICBTb21lIFIgYmFzaWNzDQoNCi0gICBEYXRhIGluIFINCg0KLSAgIEdyYXBoaWNzIHdpdGggZ2dwbG90DQoNCi0gICBTaW1wbGUgU3RhdGlzdGljcyBpbiBSDQoNCi0gICBSZXByb2R1Y2libGUgcmVwb3J0cyB3aXRoIFIgbWFya2Rvd24NCg0KIyMgQ2FuYWlzIG5vIFlvdXR1YmUgeyNzZWMtY2FuYWlzLW5vLXlvdXR1YmV9DQoNCltQYXQgU2NobG9zc10oaHR0cHM6Ly93d3cueW91dHViZS5jb20vQFJpZmZvbW9uYXMpICNlc3NlIGNhcmEgw6kgZ2VuaWFsDQoNCltBbWJpZW50YWwgUHJvIERldl0oaHR0cHM6Ly93d3cueW91dHViZS5jb20vQGFtYmllbnRhbHByb2RldjUzNzkpDQoNCltNYXJjZWxvIENhcnZhbGhvIFJpYmVpcm8gLSBZb3V0dWJlXShodHRwczovL3d3dy55b3V0dWJlLmNvbS9AY2FydmFsaG9yaWJlaXJvKQ0KDQotICAgVGVtIG8gW0Jsb2ddKGh0dHBzOi8vY2FydmFsaG9yaWJlaXJvLm5ldGxpZnkuYXBwLykgZGVsZSB0YW1iw6ltLg0KDQpbRmVybmFuZGEgUGVyZXNdKGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL0BGZXJuYW5kYVBlcmVzKQ0KDQpbTWFyaW4gU3RhdHNdKGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL0BtYXJpbnN0YXRsZWN0dXJlcykNCg0KIyBBaW5kYSBwcmVjaXNhIHNlciBpbXBsZW1lbnRhZG8vYWp1c3RhZG8geyNzZWMtYWluZGEtcHJlY2lzYS1zZXItaW1wbGVtZW50YWRvYWp1c3RhZG8gLnVubnVtYmVyZWR9DQoNCi0gICBSU8OBZ3VhIGRldmUgYnVzY2FyIGRhZG9zIGFudGVyaW9yZXMgYSAyMDE1Lg0KLSAgIEEgRmVwYW0gdGVtIG9zIGRhZG9zIGRlIGBhbHRpdHVkZWAgZGFzIGVzdGHDp8O1ZXMuIEEgcGFydGlyIGRpc3NvIHBvZGUgc2VyIGNhbGN1bGFkbyBvIGAlIGRlIHNhdHVyYcOnw6NvIGRlIE94aWfDqm5pbyBEaXNzb2x2aWRvYCwgbmVjZXNzw6FyaW8gcGFyYSBvIGPDoWxjdWxvIGRvIElRQS4NCi0gICBUb3JuYXIgYSBjb2x1bmEgZGUgYGNodXZhXzI0aGAgY29tbyBmYWN0b3IuDQotICAgQSBjb2x1bmEgYGhvcmFfY29sZXRhYCBlc3TDoSBjb20gZm9ybWF0byBpbmNvcnJldG8uDQotICAgR2VyYXIgdW0gYFNoaW55IFdlYiBBcHBgDQotICAgfn5Ub3JuYXIgYSBjb2x1bmEgZGUgYG11bmljaXBpb2AgY29tIGFwZW5hcyBhIHByaW1laXJhIGxldHJhIG1hacO6c2N1bGEufn4NCi0gICBTaW5jcm9uaXphw6fDo28gdmlhIEdpdEh1Yg0KLSAgIEFwcmVuZGVyIGEgZ2VyYXIgbyBtYXBhIGRlIHByZWNpcGl0YcOnw6NvIG1lbnNhbCBwcmEgdG9kbyBvIFJTDQogICAgLSAgIE8gUlMgZXN0w6EgZW50cmUgMiBmdXNvcywgZW50w6NvIGFjYWJhICJwYXJ0aW5kbyBubyBtZWlvIiBhIGZpZ3VyYQ0KLSAgIEZ1dHVyYW1lbnRlOiBpbnRlZ3Jhw6fDo28gdmlhIEdvb2dsZSBTaGVldHMuDQoNCiMgSW5mb3JtYcOnw7VlcyBhZGljaW9uYWlzIHsjc2VjLWluZm9ybWHDp8O1ZXMtYWRpY2lvbmFpcyAudW5udW1iZXJlZH0NCg0KRS1tYWlsIHBhcmEgY29udGF0bzogW2xlb25hcmRvZndpbmtcQGdtYWlsLmNvbV0obGVvbmFyZG9md2lua0BnbWFpbC5jb20pDQoNCkdpdEh1YjogPGh0dHBzOi8vZ2l0aHViLmNvbS9sZW9uYXJkb2Z3aW5rLz4NCg0KTGlua2VkSW46IDxodHRwczovL3d3dy5saW5rZWRpbi5jb20vaW4vbGVvbmFyZG9md2luay8+DQoNCmBgYHtyIGluY2x1ZGUgPSBGQUxTRX0NCiMgbm8gWUFNTCBkbyBjb2RlIGNodW5rOg0KIyBwcmEgZXNjb25kZXIgbyBjw7NkaWdvDQoNCiMgY2xhc3Muc291cmNlID0gJ2ZvbGQtaGlkZScgDQojIGZvbGQub3V0cHV0PUZBTFNFLCANCiMgZm9sZC5wbG90PUZBTFNFDQpgYGANCg==